我现在在做一项前端技改,是根据特定的数据结构,利用vue2+element-ui来生成动态表单的一项功能。
我提供如下formConfig的数据结构。代码中有对应的说明注释。其中 fields 为数组结构,其中的元素描述的是表单中的每一项元素。fieldId为提交的元素字段,fieldName为属性中文名,fieldType是element-ui对应的组件类型,fieldValueType是格式类型,required为是否必填,其他的字段对应可映射为对应表单元素的属性,其他附加信息可以参考如下代码中的注释,注释中会对当前属性进行详细说明。
想要通过提供的formConfig数据,来生成对应的element-ui动态表单,请给出实现代码。
const formConfig = {
pageId: 'user_profile',
fields: [
{
fieldId: 'username',
fieldName: '用户名',
fieldType: 'input',
fieldValueType: 'string', // 支持多种文件类型:string/integer/boolean/decimal/date/pdf/word/excel
required: true, // 判断是否必填
maxLength: 20, // 最大长度限制
placeholder: '请输入用户名',
},
{
fieldId: 'assets',
fieldName: '资产',
fieldType: 'input',
fieldValueType: 'number',
required: true,
maxLength: 20,
placeholder: '请输入用户名',
suffix: '元', // 放在输入框后的单位
},
{
fieldId: 'intro',
fieldName: '个人简介',
fieldType: 'textarea',
fieldValueType: 'string',
required: false,
maxLength: 200,
placeholder: '请简要介绍自己',
rows: 4
},
{
fieldId: 'userage',
fieldName: '用户年龄段',
fieldType: 'select',// 下拉选择框类型
fieldValueType: 'string',
required: true,
// 下拉选项配置
dropdownOptions: [
{ value: 18, label: '小于18' },
{ value: 30, label: '18-30' },
{ value: 60, label: '30-60' },
{ value: 100, label: '大于60' }
]
},
{
fieldId: 'userType',
fieldName: '用户类型',
fieldType: 'select',
fieldValueType: 'string',
required: true, // 是否必填
// 依赖条件配置
condition: {
trigRule: 'userage=18', // 触发规则:fieldId=特定value的形式
displayType: 'hide' // 展示控制类型:展示但是控制是否可用-enable|disable,或隐藏-hide
},
// 默认选项
dropdownOptions: [
{ value: 'normal', label: '普通用户' },
{ value: 'vip', label: 'VIP用户' }
],
// 其他依赖条件下的选项变化
otherOptions: {
// 当userage=30时的选项
'userage=30': [
{ value: 'normal', label: '普通用户22' },
{ value: 'vip', label: 'VIP用户22' }
]
}
},
{
fieldId: 'vipLevel',
fieldName: 'VIP等级',
fieldType: 'select',
fieldValueType: 'string',
required: false,
condition: {
trigRule: 'userType=vip',
displayType: 'hide'
},
dropdownOptions: [
{ value: 1, label: 'vip1' },
{ value: 2, label: 'vip2' },
{ value: 3, label: 'vip3' },
{ value: 4, label: 'vip4' }
]
},
{
fieldId: 'gender',
fieldName: '性别',
fieldType: 'radio',
fieldValueType: 'string',
required: true,
dropdownOptions: [
{ value: 'male', label: '男' },
{ value: 'female', label: '女' }
]
},
{
fieldId: 'hobbies',
fieldName: '兴趣爱好',
fieldType: 'checkbox',
fieldValueType: 'array',
required: false,
dropdownOptions: [
{ value: 'reading', label: '阅读' },
{ value: 'sports', label: '运动' },
{ value: 'music', label: '音乐' },
{ value: 'travel', label: '旅行' }
]
},
{
fieldId: 'birthday',
fieldName: '生日',
fieldType: 'date',
fieldValueType: 'date',
required: false,
placeholder: '选择日期'
},
{
fieldId: 'workTime',
fieldName: '工作时间',
fieldType: 'time',
fieldValueType: 'string',
required: false,
placeholder: '选择时间'
},
{
fieldId: 'validDateTime',
fieldName: '有效日期时间',
fieldType: 'dateTime', // 日期时间选择器
fieldValueType: 'string',
required: true, // 必填项
// 如果发现表单元素中有maxCount字段,则说明该表单中支持存在最多maxCount个该类元素。
// 最少支持1个,最多支持maxCount个,可在该元素后通过+/-号控制数量,fieldId/fieldName末尾加序号区分,序号从1开始,及1-maxCount。
maxCount: 5
},
{
fieldId: 'avatar',
fieldName: '头像',
fieldType: 'file',
fieldValueType: 'array',
required: false,
}
]
};
<template>
<div class="form-container">
<el-form ref="dynamicForm" :model="formData" label-width="120px" label-position="top" class="dynamic-form">
<!-- 遍历所有字段配置 -->
<div v-for="field in config.fields" :key="field.fieldId">
<!-- 普通字段 -->
<div v-if="!field.maxCount" class="form-card" v-show="shouldShowField(field)">
<div class="form-title">
<i :class="getFieldIcon(field.fieldType)"></i>
{{ field.fieldName }}
<span v-if="field.required" style="color: #F56C6C; margin-left: 5px">*</span>
</div>
<!-- 输入框 -->
<el-form-item v-if="field.fieldType === 'input' || field.fieldType === 'textarea'" :prop="field.fieldId"
:rules="getRules(field)">
<el-input v-if="field.fieldType === 'input'" v-model="formData[field.fieldId]"
:placeholder="field.placeholder || '请输入'" :maxlength="field.maxLength"
:disabled="isFieldDisabled(field)"></el-input>
<el-input v-else-if="field.fieldType === 'textarea'" type="textarea" v-model="formData[field.fieldId]"
:placeholder="field.placeholder || '请输入'" :maxlength="field.maxLength" :rows="4"
:disabled="isFieldDisabled(field)"></el-input>
</el-form-item>
<!-- 下拉选择 -->
<el-form-item v-else-if="field.fieldType === 'select'" :prop="field.fieldId" :rules="getRules(field)">
<el-select v-model="formData[field.fieldId]" :placeholder="field.placeholder || '请选择'" style="width: 100%"
:disabled="isFieldDisabled(field)">
<el-option v-for="option in getDropdownOptions(field)" :key="option.value" :label="option.label"
:value="option.value"></el-option>
</el-select>
</el-form-item>
<!-- 日期时间选择器 -->
<el-form-item v-else-if="field.fieldType === 'dateTime'" :prop="field.fieldId" :rules="getRules(field)">
<el-date-picker v-model="formData[field.fieldId]" type="datetime" placeholder="选择日期时间" style="width: 100%"
:disabled="isFieldDisabled(field)"></el-date-picker>
</el-form-item>
</div>
<!-- 可动态增减的字段组 -->
<div v-else class="dynamic-group">
<div class="group-header">
<div class="group-title">
<i class="el-icon-tickets"></i>
{{ field.fieldName }} ({{ formData[field.fieldId].length }}/{{ field.maxCount }})
</div>
<div class="group-actions">
<el-tooltip content="添加一项" placement="top">
<el-button type="success" icon="el-icon-plus" circle size="mini" @click="addFieldItem(field)"
:disabled="formData[field.fieldId].length >= field.maxCount"></el-button>
</el-tooltip>
</div>
</div>
<div v-for="(item, index) in formData[field.fieldId]" :key="index">
<div class="form-card">
<div class="form-title">
<i :class="getFieldIcon(field.fieldType)"></i>
{{ field.fieldName }} {{ index + 1 }}
<span v-if="field.required" style="color: #F56C6C; margin-left: 5px">*</span>
</div>
<el-form-item :prop="`${field.fieldId}.${index}`" :rules="getRules(field)">
<!-- 日期时间选择器 -->
<el-date-picker v-if="field.fieldType === 'dateTime'" v-model="formData[field.fieldId][index]"
type="datetime" placeholder="选择日期时间" style="width: 100%"></el-date-picker>
<!-- 其他类型字段可以在这里扩展 -->
</el-form-item>
<div style="text-align: right; margin-top: -10px">
<el-button type="danger" icon="el-icon-delete" size="mini" @click="removeFieldItem(field, index)"
:disabled="formData[field.fieldId].length <= 1">删除</el-button>
</div>
</div>
</div>
</div>
</div>
</el-form>
<div class="form-actions">
<el-button type="primary" @click="submitForm" size="medium">提交表单</el-button>
<el-button @click="resetForm" size="medium">重置表单</el-button>
<el-button @click="showFormData = !showFormData" size="medium">
{{ showFormData ? '隐藏数据' : '查看数据' }}
</el-button>
</div>
<div v-if="showFormData" class="json-view">
<div class="json-view-header">
<span>表单数据 (JSON格式)</span>
<el-button type="text" @click="copyJson" style="color: #67c23a;">
<i class="el-icon-document-copy"></i> 复制JSON
</el-button>
</div>
<pre>{{ formatJson(formData) }}</pre>
</div>
</div>
</template>
<script>
import { formConfig } from './demo2'
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
// 初始化表单数据
const formData = {};
formConfig.fields.forEach(field => {
if (field.maxCount) {
// 可动态增减的字段组初始化为数组
formData[field.fieldId] = [null];
} else {
// 普通字段初始化为null
formData[field.fieldId] = null;
}
});
return {
config: formConfig,
formData: formData,
showFormData: false
};
},
methods: {
// 获取字段图标
getFieldIcon(fieldType) {
const icons = {
input: 'el-icon-edit',
textarea: 'el-icon-document',
select: 'el-icon-s-operation',
dateTime: 'el-icon-date',
radio: 'el-icon-circle-check',
checkbox: 'el-icon-check',
file: 'el-icon-paperclip',
url: 'el-icon-link'
};
return icons[fieldType] || 'el-icon-question';
},
// 获取验证规则
getRules(field) {
const rules = [];
if (field.required) {
rules.push({
required: true,
message: `请输入${field.fieldName}`,
trigger: 'blur'
});
}
return rules;
},
// 检查条件是否满足(支持多个条件)
checkCondition(trigRule) {
if (!trigRule) return false;
// 分割多个条件
const conditions = trigRule.split('&');
// 检查每个条件是否满足
return conditions.every(condition => {
const [fieldId, expectedValue] = condition.split('=');
const actualValue = this.formData[fieldId];
// 处理数字类型的比较
if (typeof actualValue === 'number' && !isNaN(expectedValue)) {
return actualValue === Number(expectedValue);
}
// 默认使用宽松比较
return actualValue == expectedValue;
});
},
// 判断字段是否应该显示
shouldShowField(field) {
if (!field.condition) return true;
const conditionMet = this.checkCondition(field.condition.trigRule);
// 如果条件满足且显示类型是隐藏,则不显示
if (field.condition.displayType === 'hide') {
return !conditionMet;
}
// 其他情况都显示
return true;
},
// 判断字段是否被禁用
isFieldDisabled(field) {
if (!field.condition) return false;
const conditionMet = this.checkCondition(field.condition.trigRule);
// 如果条件满足且显示类型是禁用,则禁用字段
if (field.condition.displayType === 'disable') {
return conditionMet;
}
return false;
},
// 获取下拉选项
getDropdownOptions(field) {
if (!field.otherOptions) return field.dropdownOptions;
// 检查是否有满足条件的otherOptions
for (const condition in field.otherOptions) {
if (this.checkCondition(condition)) {
return field.otherOptions[condition];
}
}
return field.dropdownOptions;
},
// 添加字段项
addFieldItem(field) {
if (this.formData[field.fieldId].length < field.maxCount) {
this.formData[field.fieldId].push(null);
}
},
// 删除字段项
removeFieldItem(field, index) {
if (this.formData[field.fieldId].length > 1) {
this.formData[field.fieldId].splice(index, 1);
}
},
// 提交表单
submitForm() {
this.$refs.dynamicForm.validate(valid => {
if (valid) {
this.$message.success('表单验证通过!');
this.showFormData = true;
console.log('-------->', this.formData)
} else {
this.$message.error('请填写完整表单信息');
return false;
}
});
},
// 重置表单
resetForm() {
this.$refs.dynamicForm.resetFields();
this.showFormData = false;
// 重置动态字段组
this.config.fields.forEach(field => {
if (field.maxCount) {
this.formData[field.fieldId] = [null];
}
});
},
// 格式化JSON显示
formatJson(obj) {
return JSON.stringify(obj, null, 2);
},
// 复制JSON
copyJson() {
const textarea = document.createElement('textarea');
textarea.value = JSON.stringify(this.formData, null, 2);
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
this.$message.success('JSON已复制到剪贴板');
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<template>
<div class="form-container">
<h2 class="form-title">动态生成表单</h2>
<el-form :model="formData" :rules="formRules" ref="dynamicForm" label-width="140px" label-position="right">
<!-- 遍历字段配置 -->
<template v-for="field in formConfig.fields">
<!-- 处理可动态添加的字段 -->
<template v-if="field.maxCount > 1">
<div class="field-group" :key="field.fieldId">
<div class="field-group-header">
<span class="field-group-title">{{ field.fieldName }}</span>
<span class="field-count">({{ getFieldCount(field.fieldId) }}/{{ field.maxCount }})</span>
</div>
<el-button v-if="getFieldCount(field.fieldId) < field.maxCount" class="add-item-btn" type="primary"
icon="el-icon-plus" size="small" @click="addDynamicField(field)">
添加{{ field.fieldName }}
</el-button>
<div v-for="index in getFieldCount(field.fieldId)" :key="index">
<el-form-item :label="field.fieldName + ' ' + index + ':'" :prop="getDynamicFieldId(field.fieldId, index)"
:rules="getValidationRules(field)">
<!-- 日期时间范围选择器 -->
<el-date-picker v-if="field.fieldType === 'dateTime' && field.isRange"
v-model="formData[getDynamicFieldId(field.fieldId, index)]" type="datetimerange"
:placeholder="field.placeholder || '选择日期时间范围'" style="width: 100%" value-format="yyyy-MM-dd HH:mm:ss"
range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
</el-date-picker>
<!-- 其他字段类型的渲染 -->
<template v-else>
<!-- 这里可以添加其他字段类型的渲染 -->
<el-input v-if="field.fieldType === 'input'"
v-model="formData[getDynamicFieldId(field.fieldId, index)]" :placeholder="field.placeholder || ''"
:maxlength="field.maxLength" clearable>
<template v-slot:suffix v-if="field.suffix">
{{ field.suffix }}
</template>
</el-input>
</template>
<el-button v-if="getFieldCount(field.fieldId) > 1" class="remove-btn" type="danger"
icon="el-icon-delete" size="mini" circle @click="removeDynamicField(field, index)"></el-button>
</el-form-item>
</div>
</div>
</template>
<!-- 普通字段 -->
<template v-else>
<!-- 条件判断是否显示 -->
<div v-if="shouldShowField(field)" :key="field.fieldId">
<el-form-item :label="field.fieldName + ':'" :prop="field.fieldId" :rules="getValidationRules(field)">
<!-- 输入框 -->
<el-input v-if="field.fieldType === 'input' || field.fieldType === 'textarea'"
v-model="formData[field.fieldId]" :type="field.fieldType" :placeholder="field.placeholder || ''"
:maxlength="field.maxLength" :rows="field.rows || 2" clearable>
<template v-slot:suffix v-if="field.suffix">
{{ field.suffix }}
</template>
</el-input>
<!-- 下拉选择框 -->
<el-select v-else-if="field.fieldType === 'select'" v-model="formData[field.fieldId]"
:placeholder="field.placeholder || '请选择'" clearable style="width: 100%">
<el-option v-for="option in getDropdownOptions(field)" :key="option.value" :label="option.label"
:value="option.value">
</el-option>
</el-select>
<!-- 单选框 -->
<el-radio-group v-else-if="field.fieldType === 'radio'" v-model="formData[field.fieldId]">
<el-radio v-for="option in field.dropdownOptions" :key="option.value" :label="option.value">
{{ option.label }}
</el-radio>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group v-else-if="field.fieldType === 'checkbox'" v-model="formData[field.fieldId]">
<el-checkbox v-for="option in field.dropdownOptions" :key="option.value" :label="option.value">
{{ option.label }}
</el-checkbox>
</el-checkbox-group>
<!-- 日期选择器 -->
<el-date-picker v-else-if="field.fieldType === 'date'" v-model="formData[field.fieldId]"
:type="field.isRange ? 'daterange' : 'date'"
:placeholder="field.placeholder || (field.isRange ? '选择日期范围' : '选择日期')" style="width: 100%"
value-format="yyyy-MM-dd" :range-separator="field.isRange ? '至' : ''"
:start-placeholder="field.isRange ? '开始日期' : ''" :end-placeholder="field.isRange ? '结束日期' : ''">
</el-date-picker>
<!-- 时间选择器 -->
<el-time-picker v-else-if="field.fieldType === 'time'" v-model="formData[field.fieldId]"
:is-range="field.isRange" :placeholder="field.placeholder || (field.isRange ? '选择时间范围' : '选择时间')"
style="width: 100%" value-format="HH:mm:ss" :range-separator="field.isRange ? '至' : ''"
:start-placeholder="field.isRange ? '开始时间' : ''" :end-placeholder="field.isRange ? '结束时间' : ''">
</el-time-picker>
<!-- 日期时间选择器 -->
<el-date-picker v-else-if="field.fieldType === 'dateTime'" v-model="formData[field.fieldId]"
:type="field.isRange ? 'datetimerange' : 'datetime'"
:placeholder="field.placeholder || (field.isRange ? '选择日期时间范围' : '选择日期时间')" style="width: 100%"
value-format="yyyy-MM-dd HH:mm:ss" :range-separator="field.isRange ? '至' : ''"
:start-placeholder="field.isRange ? '开始日期' : ''" :end-placeholder="field.isRange ? '结束日期' : ''">
</el-date-picker>
<!-- 文件上传 -->
<el-upload v-else-if="field.fieldType === 'file'" action="#" :auto-upload="false"
:on-change="(file) => handleFileChange(file, field)" :file-list="formData[field.fieldId]" multiple>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">请上传文件</div>
</el-upload>
</el-form-item>
</div>
</template>
</template>
</el-form>
</div>
</template>
<script>
// import { formConfig } from './demo2'
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
formData: {},
formRules: {},
dynamicFields: {}, // 存储动态添加的字段信息
formConfig: {
pageId: 'user_profile',
fields: [
{
fieldId: 'username',
fieldName: '用户名',
fieldType: 'input',
fieldValueType: 'string',
required: true,
maxLength: 20,
placeholder: '请输入用户名',
},
{
fieldId: 'assets',
fieldName: '资产',
fieldType: 'input',
fieldValueType: 'number',
required: true,
maxLength: 20,
placeholder: '请输入资产',
suffix: '元',
},
{
fieldId: 'intro',
fieldName: '个人简介',
fieldType: 'textarea',
fieldValueType: 'string',
required: false,
maxLength: 200,
placeholder: '请简要介绍自己',
rows: 4
},
{
fieldId: 'userage',
fieldName: '用户年龄段',
fieldType: 'select',
fieldValueType: 'string',
required: true,
dropdownOptions: [
{ value: 18, label: '小于18' },
{ value: 30, label: '18-30' },
{ value: 60, label: '30-60' },
{ value: 100, label: '大于60' }
]
},
{
fieldId: 'userType',
fieldName: '用户类型',
fieldType: 'select',
fieldValueType: 'string',
required: true,
condition: {
trigRule: 'userage=18',
displayType: 'hide'
},
dropdownOptions: [
{ value: 'normal', label: '普通用户' },
{ value: 'vip', label: 'VIP用户' }
],
otherOptions: {
'userage=30': [
{ value: 'normal', label: '普通用户22' },
{ value: 'vip', label: 'VIP用户22' }
]
}
},
{
fieldId: 'vipLevel',
fieldName: 'VIP等级',
fieldType: 'select',
fieldValueType: 'string',
required: false,
condition: {
trigRule: 'userType=vip',
displayType: 'hide'
},
dropdownOptions: [
{ value: 1, label: 'vip1' },
{ value: 2, label: 'vip2' },
{ value: 3, label: 'vip3' },
{ value: 4, label: 'vip4' }
]
},
{
fieldId: 'gender',
fieldName: '性别',
fieldType: 'radio',
fieldValueType: 'string',
required: true,
dropdownOptions: [
{ value: 'male', label: '男' },
{ value: 'female', label: '女' }
]
},
{
fieldId: 'hobbies',
fieldName: '兴趣爱好',
fieldType: 'checkbox',
fieldValueType: 'array',
required: false,
dropdownOptions: [
{ value: 'reading', label: '阅读' },
{ value: 'sports', label: '运动' },
{ value: 'music', label: '音乐' },
{ value: 'travel', label: '旅行' }
]
},
{
fieldId: 'birthday',
fieldName: '生日',
fieldType: 'date',
fieldValueType: 'date',
required: false,
placeholder: '选择日期'
},
{
fieldId: 'workTime',
fieldName: '工作时间',
fieldType: 'time',
isRange: true,
fieldValueType: 'string',
required: false,
placeholder: '选择时间'
},
{
fieldId: 'validDateTime',
fieldName: '有效日期时间',
fieldType: 'dateTime',
fieldValueType: 'string',
isRange: true,
required: true,
maxCount: 5
},
{
fieldId: 'avatar',
fieldName: '头像',
fieldType: 'file',
fieldValueType: 'array',
required: false,
}
]
}
};
},
created() {
// 初始化表单数据
this.initFormData();
// 初始化动态字段
this.initDynamicFields();
},
methods: {
// 初始化表单数据
initFormData() {
this.formConfig.fields.forEach(field => {
// 根据字段类型设置初始值
if (field.fieldType === 'checkbox') {
this.$set(this.formData, field.fieldId, []);
} else if (field.fieldType === 'file') {
this.$set(this.formData, field.fieldId, []);
} else if (field.isRange && (field.fieldType === 'date' || field.fieldType === 'time' || field.fieldType === 'dateTime')) {
this.$set(this.formData, field.fieldId, []);
} else {
this.$set(this.formData, field.fieldId, '');
}
});
},
// 初始化动态字段
initDynamicFields() {
this.formConfig.fields.forEach(field => {
if (field.maxCount > 1) {
// 初始化动态字段计数
this.$set(this.dynamicFields, field.fieldId, 1);
// 初始化第一个动态字段的值
this.$set(this.formData, this.getDynamicFieldId(field.fieldId, 1), '');
}
});
},
// 获取动态字段ID
getDynamicFieldId(fieldId, index) {
return `${fieldId}${index}`;
},
// 获取动态字段数量
getFieldCount(fieldId) {
return this.dynamicFields[fieldId] || 0;
},
// 添加动态字段
addDynamicField(field) {
if (this.dynamicFields[field.fieldId] < field.maxCount) {
this.dynamicFields[field.fieldId]++;
const newIndex = this.dynamicFields[field.fieldId];
this.$set(this.formData, this.getDynamicFieldId(field.fieldId, newIndex), '');
}
},
// 移除动态字段
removeDynamicField(field, index) {
if (this.dynamicFields[field.fieldId] > 1) {
// 删除表单数据
this.$delete(this.formData, this.getDynamicFieldId(field.fieldId, index));
// 重新组织动态字段
const currentCount = this.dynamicFields[field.fieldId];
for (let i = index + 1; i <= currentCount; i++) {
const value = this.formData[this.getDynamicFieldId(field.fieldId, i)];
this.$set(this.formData, this.getDynamicFieldId(field.fieldId, i - 1), value);
this.$delete(this.formData, this.getDynamicFieldId(field.fieldId, i));
}
this.dynamicFields[field.fieldId]--;
}
},
// 获取验证规则
getValidationRules(field) {
const rules = [];
if (field.required) {
rules.push({
required: true,
message: `${field.fieldName}是必填项`,
trigger: field.fieldType === 'input' || field.fieldType === 'textarea' ? 'blur' : 'change'
});
}
if (field.maxLength && (field.fieldType === 'input' || field.fieldType === 'textarea')) {
rules.push({
max: field.maxLength,
message: `最大长度不能超过${field.maxLength}个字符`,
trigger: 'blur'
});
}
return rules;
},
// 获取下拉选项
getDropdownOptions(field) {
// 检查是否有条件选项
if (field.otherOptions) {
for (const condition in field.otherOptions) {
const [conditionField, conditionValue] = condition.split('=');
if (this.formData[conditionField] == conditionValue) {
return field.otherOptions[condition];
}
}
}
return field.dropdownOptions || [];
},
// 判断字段是否显示
shouldShowField(field) {
if (!field.condition) return true;
const { trigRule, displayType } = field.condition;
const [fieldId, value] = trigRule.split('=');
if (displayType === 'hide') {
return this.formData[fieldId] != value;
}
return true;
},
// 文件上传处理
handleFileChange(file, field) {
if (!this.formData[field.fieldId]) {
this.$set(this.formData, field.fieldId, []);
}
this.formData[field.fieldId].push(file);
},
// 提交表单
submitForm() {
this.$refs.dynamicForm.validate((valid) => {
if (valid) {
this.$message.success('表单验证成功!');
console.log('表单数据:', this.formData);
} else {
this.$message.error('表单验证失败,请检查输入!');
return false;
}
});
},
// 重置表单
resetForm() {
this.$refs.dynamicForm.resetFields();
// 重置动态字段
this.initDynamicFields();
this.$message.info('表单已重置');
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>