方式一:
<template>
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="model-ruleForm"
:size="formSize" status-icon label-position="top">
<el-form-item label="字段" required style="margin-bottom: 0"></el-form-item>
<el-form-item class="fields-container">
<el-form-item style="width: 100%; margin-bottom: 5px">
<el-col :span="2">序号</el-col><el-col :span="6">显示名称</el-col><el-col :span="1"></el-col><el-col
:span="6">字段名</el-col><el-col :span="1"></el-col><el-col :span="6">字段类型</el-col><el-col
:span="2" style="text-align: right">操作</el-col>
</el-form-item>
<el-form-item required v-for="(field, index) in ruleForm.fields" :key="field.key"
style="width: 100%; margin-bottom: 10px">
<el-col :span="2">{{ index + 1 }}</el-col>
<el-col :span="6">
<el-form-item :prop="'fields.' + index + '.fieldChineseName'" :rules="[
{
required: true,
message: '请输入显示名',
trigger: 'blur',
},
]">
<el-input v-model="field.fieldChineseName" placeholder="显示名" />
</el-form-item>
</el-col>
<el-col :span="1"></el-col>
<el-col class="text-center" :span="6">
<el-form-item :prop="'fields.' + index + '.fieldEnglishName'" :rules="[
{
required: true,
message: '请输入字段名',
trigger: 'blur',
},
]">
<el-input v-model="field.fieldEnglishName" placeholder="字段名" />
</el-form-item>
</el-col>
<el-col :span="1"></el-col>
<el-col :span="6">
<el-form-item :prop="'fields.' + index + '.fieldType'" :rules="[
{
required: true,
message: '请选择类型',
trigger: 'change',
},
]">
<el-select v-model="field.fieldType" placeholder="字段类型">
<el-option label="单行文本" value="shanghai" />
<el-option label="多行文本" value="beijing" />
<el-option label="下拉框" value="shanghai" />
<el-option label="计数器" value="beijing" />
<el-option label="开关" value="shanghai" />
<el-option label="日期" value="beijing" />
<el-option label="固定时间" value="shanghai" />
<el-option label="任意时间" value="beijing" />
<el-option label="单选" value="shanghai" />
<el-option label="多选" value="beijing" />
<el-option label="图片" value="shanghai" />
<el-option label="文件" value="beijing" />
<el-option label="图标选择" value="shanghai" />
<el-option label="描述框" value="beijing" />
<el-option label="链接" value="shanghai" />
<el-option label="网页" value="beijing" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="2"><svg class="icon" aria-hidden="true" @click.prevent="removeField(field)"
style="float: right; cursor: pointer">
<use xlink:href="#icon-minus_full"></use>
</svg></el-col>
</el-form-item>
<el-form-item style="width: 100%;">
<el-col :span="2"></el-col>
<el-col :span="22" style="display: flex; align-items: center;">
<svg class="icon" aria-hidden="true" @click.prevent="addField"
style="float: right; cursor: pointer">
<use xlink:href="#icon-xinzeng"></use>
</svg>
<el-button type="primary" link @click="addField">新增</el-button>
</el-col>
</el-form-item>
</el-form-item>
<el-form-item>
<el-button @click="resetForm(ruleFormRef)" size="small">重置</el-button>
<el-button type="primary" @click="submitForm(ruleFormRef)" size="small">提交</el-button></el-form-item>
</el-form>
</template>
<script setup>
import { ref, reactive, defineExpose } from "vue";
const ruleFormRef = ref();
const ruleForm = reactive({
fields: [
{
key: 1,
value: "",
fieldChineseName: "",
fieldEnglishName: "",
fieldType: "",
},
],
});
const removeField = (item) => {
const index = ruleForm.fields.indexOf(item);
if (index !== -1) {
ruleForm.fields.splice(index, 1);
}
};
const addField = () => {
ruleForm.fields.push({
key: Date.now(),
value: "",
fieldChineseName: "",
fieldEnglishName: "",
fieldType: "",
});
};
const submitForm = async (formEl) => {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
console.log("ruleForm!");
console.log(ruleForm);
} else {
console.log("error submit!", fields);
}
});
};
const resetForm = (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped>
.fields-container {
background: rgb(245, 246, 247);
padding: 10px 20px;
}
.fields-container /deep/ .el-input__wrapper {
background-color: rgb(255, 255, 255) !important;
box-shadow: none !important;
}
.fields-container /deep/ .el-select__wrapper{
box-shadow: none !important;
}
.dialog-footer button:first-child {
margin-right: 10px;
}
.model-ruleForm /deep/ .el-form-item__error {
left: auto !important;
right: 45px !important;
top: 40% !important;
}
</style>
方式二:
<template>
<el-form ref="formName" :model="studentData">
<el-table :data="studentData.studentList" stripe>
<el-table-column label="姓名" align="left">
<template slot-scope="scope">
<el-form-item
size="small"
:prop="'studentList.' + scope.$index + '.name'"
:rules="rules.name"
>
<el-input v-model="scope.row.name" placeholder="请输入姓名" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="性别">
<template slot-scope="scope">
<el-form-item
size="small"
:prop="'studentList.' + scope.$index + '.sex'"
:rules="rules.sex"
>
<el-select v-model="scope.row.sex" placeholder="请选择性别">
<el-option label="男" value="1"></el-option>
<el-option label="女" value="0"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button
type="text"
id="delete-btn"
@click="deleteRow(scope.row, scope.$index)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<div style="margin: 20px; text-align: right">
<el-button @click="addRow" size="small">新增</el-button>
<el-button @click="saveData('formName')" size="small">确定</el-button>
</div>
</el-form>
</template>
<script>
export default {
data() {
return {
studentData: {
studentList: [
{
name: "王小虎",
sex: "男",
},
{
name: "Linda",
sex: "女",
},
],
},
//验证规则
rules: {
name: [
{
required: true,
message: "请输入姓名",
trigger: ["blur", "change"],
},
],
sex: [
{
required: true,
message: "请选择性别",
trigger: ["blur", "change"],
},
],
},
};
},
methods: {
// 添加一行
addRow() {
const item = {
name: "",
sex: "",
};
this.studentData.studentList.push(item);
},
// 删除一行
deleteRow(row, index) {
this.studentData.studentList.splice(index, 1);
},
saveData(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert("submit!");
} else {
console.log("error submit!!");
return false;
}
});
},
},
};
</script>
<style scoped>
.el-form {
width: 60%;
background: white;
border: 1px solid gainsboro;
}
/deep/ .el-input {
width: 100%;
}
</style>
效果
点击新增,table新增一行,点击删除,删除所在行。若验证不通过,点击“确定”,提示如下图