<template>
<el-form ref="formRef" :model="formData" :rules="rules">
<el-table :data="formData.rows" border>
<el-table-column label="序号" type="index" width="50"></el-table-column>
<el-table-column label="名称" prop="name">
<template #default="{ row }">
<el-form-item :prop="'rows.' + row.id + '.name'" :rules="rules.name">
<el-input v-model="row.name"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="图片" prop="images">
<template #default="{ row }">
<el-form-item :prop="'rows.' + row.id + '.images'" :rules="rules.images">
<el-upload
v-model:file-list="row.images"
action="#"
list-type="picture-card"
:limit="3"
:on-exceed="handleExceed"
>
<el-icon><Plus /></el-icon>
</el-upload>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="视频" prop="videos">
<template #default="{ row }">
<el-form-item :prop="'rows.' + row.id + '.videos'" :rules="rules.videos">
<el-upload
v-model:file-list="row.videos"
action="#"
:limit="2"
:on-exceed="handleExceed"
>
<el-button type="primary">上传视频</el-button>
</el-upload>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="项目和分类和数目" prop="items">
<template #default="{ row }">
<el-form-item
v-for="(item, index) in row.items"
:key="index"
:prop="'rows.' + row.id + '.items.' + index"
:rules="rules.items"
>
<el-select v-model="item.project" placeholder="项目">
<el-option v-for="option in projectOptions" :key="option.value" :label="option.label" :value="option.value"></el-option>
</el-select>
<el-select v-model="item.category" placeholder="分类">
<el-option v-for="option in categoryOptions" :key="option.value" :label="option.label" :value="option.value"></el-option>
</el-select>
<el-select v-model="item.number" placeholder="数目">
<el-option v-for="option in numberOptions" :key="option.value" :label="option.label" :value="option.value"></el-option>
</el-select>
<el-button @click="removeItem(row, index)" v-if="row.items.length > 1">-</el-button>
</el-form-item>
<el-button @click="addItem(row)" v-if="row.items.length < 8">+</el-button>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark">
<template #default="{ row }">
<el-form-item :prop="'rows.' + row.id + '.remark'">
<el-input v-model="row.remark" type="textarea"></el-input>
</el-form-item>
</template>
</el-table-column>
</el-table>
<el-button @click="addRow" :disabled="formData.rows.length >= 6">新增行</el-button>
<el-button @click="removeRow" :disabled="formData.rows.length <= 1">删除行</el-button>
<el-button type="primary" @click="submitForm">提交</el-button>
</el-form>
</template>
<script lang="ts" setup>
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
const formRef = ref()
const formData = reactive({
rows: [{
id: 0,
name: '',
images: [],
videos: [],
items: [{ project: '', category: '', number: '' }],
remark: ''
}]
})
const rules = {
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
images: [{ type: 'array', required: true, min: 1, message: '请上传至少一张图片', trigger: 'change' }],
videos: [{ type: 'array', required: true, min: 1, message: '请上传至少一个视频', trigger: 'change' }],
items: [{ required: true, message: '请选择项目、分类和数目', trigger: 'change' }]
}
const projectOptions = [
{ value: 'project1', label: '项目1' },
{ value: 'project2', label: '项目2' }
]
const categoryOptions = [
{ value: 'category1', label: '分类1' },
{ value: 'category2', label: '分类2' }
]
const numberOptions = [
{ value: '1', label: '1' },
{ value: '2', label: '2' },
{ value: '3', label: '3' }
]
const handleExceed = () => {
ElMessage.warning('超出上传限制')
}
const addItem = (row) => {
if (row.items.length < 8) {
row.items.push({ project: '', category: '', number: '' })
}
}
const removeItem = (row, index) => {
if (row.items.length > 1) {
row.items.splice(index, 1)
}
}
const addRow = () => {
if (formData.rows.length < 6) {
formData.rows.push({
id: formData.rows.length,
name: '',
images: [],
videos: [],
items: [{ project: '', category: '', number: '' }],
remark: ''
})
}
}
const removeRow = () => {
if (formData.rows.length > 1) {
formData.rows.pop()
}
}
const submitForm = async () => {
if (!formRef.value) return
try {
await formRef.value.validate()
// 调用后端新增接口
console.log('表单数据:', formData.rows)
// 这里替换为您的实际API调用
// await api.addNewData(formData.rows)
ElMessage.success('提交成功')
} catch (error) {
console.error('表单验证失败:', error)
ElMessage.error('表单验证失败,请检查输入')
}
}
</script>
这个示例实现了以下功能:
- 使用
el-form
和el-table
创建一个可编辑的表格表单。 - 表格最多可以有6行,每行包含序号、名称、图片、视频、项目和分类和数目、备注列。
- 图片上传最多3张,最少1张。
- 视频上传最多2个,最少1个。
- 项目、分类和数目使用下拉框,可以动态增减,最多8个,最少1个。
- 实现了表单验证。
- 提供了新增和删除行的功能。
- 在提交表单时,会先进行验证,然后再调用后端API。
关注微信公众号温暖前端,不定期分享前端知识点和前端资料↓↓↓