js
复制代码
<template>
<div class="prop-form-container">
<!-- 渲染多个表单,每个表单对应一个数据项 --> <el-card shadow="hover" class="form-card-item">
<div v-for="(dataItem, index) in formDataList" :key="index" class="form-card">
<!-- <template #header>
<div class="card-header">
<span>属性配置 {{ index + 1 }}</span>
<el-button type="danger" link @click="removeForm(index)" :disabled="formDataList.length <= 1">
删除
</el-button>
</div>
</template> -->
<el-form :model="dataItem" label-width="80px" label-position="right" class="form-content" :inline="true">
<el-form-item :label="index + 1" label-width="10px" label-position="left"></el-form-item>
<!-- 渲染指定的四个字段 -->
<template v-for="(config, configIndex) in visibleFormConfigs" :key="configIndex">
<el-form-item :label="config.label" :prop="config.prop">
<!-- 输入框 -->
<el-input v-if="config.type === 'input'" v-model="dataItem[config.prop]" :placeholder="config.placeholder"
clearable class="form-input" />
<!-- 文本域 -->
<el-input v-else-if="config.type === 'textarea'" v-model="dataItem[config.prop]"
:placeholder="config.placeholder" type="textarea" :rows="1" class="form-textarea" />
</el-form-item>
</template>
<el-form-item label-width="10px" label-position="left">
<el-button icon="DeleteFilled" type="danger" link @click="removeForm(index)"
:disabled="formDataList.length <= 1">
</el-button></el-form-item>
</el-form>
</div>
<!-- 添加新属性按钮 -->
</el-card>
<div class="add-form-button">
<el-button type="primary" @click="addForm" icon="Plus">
添加新属性
</el-button>
<!-- 保存所有表单按钮 -->
<el-button v-if="showSaveButton" type="success" @click="saveAllFormData" icon="Check" class="save-all-button">
保存所有属性
</el-button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, Check } from '@element-plus/icons-vue'
interface FormItem {
propId: number | null
modelId: number | null
propCode: string
propName: string
propValue: string
remark: string | null
customerId: number | null
ouId: number | null
createdDate: string | null
createdBy: string | null
lastUpdatedDate: string | null
lastUpdatedBy: string | null
}
interface FormConfig {
label: string
prop: string
type: string
placeholder: string
}
interface Props {
initialData?: FormItem[]
showSaveButton?: boolean
}
const props = withDefaults(defineProps<Props>(), {
initialData: () => [],
showSaveButton: false
})
const emit = defineEmits<{
(e: 'save', data: FormItem | FormItem[]): void
}>()
// 只需要渲染的四个字段配置
const visibleFormConfigs = ref<FormConfig[]>([
{
label: "属性编码",
prop: "propCode",
type: "input",
placeholder: "例如: hsCode"
},
{
label: "属性名称",
prop: "propName",
type: "input",
placeholder: "请输入属性名称"
},
{
label: "属性数值",
prop: "propValue",
type: "input",
placeholder: "请输入属性值"
},
{
label: "备注",
prop: "remark",
type: "textarea",
placeholder: "请输入备注信息"
}
])
// 表单数据列表(包含所有字段)
const formDataList = ref<FormItem[]>([])
// 默认空表单数据
const getDefaultFormData = (): FormItem => ({
propId: null,
modelId: null,
propCode: "",
propName: "",
propValue: "",
remark: null,
customerId: null,
ouId: null,
createdDate: null,
createdBy: null,
lastUpdatedDate: null,
lastUpdatedBy: null,
})
// 初始化表单数据
const initForm = () => {
// 如果传入了初始数据,则使用传入的数据
if (props.initialData && props.initialData.length > 0) {
formDataList.value = props.initialData.map(item => ({ ...item }))
} else {
// 如果没有传入数据,初始化一个空表单
formDataList.value = [getDefaultFormData()]
}
}
// 监听 initialData 的变化
watch(
() => props.initialData,
(newVal) => {
if (newVal) {
formDataList.value = newVal.map(item => ({ ...item }))
} else {
formDataList.value = [getDefaultFormData()]
}
},
{ deep: true }
)
// 保存单个表单数据
const saveFormData = (index: number) => {
emit('save', formDataList.value[index])
ElMessage.success(`属性配置 ${index + 1} 已保存`)
}
// 保存所有表单数据
const saveAllFormData = () => {
emit('save', formDataList.value)
ElMessage.success("所有属性配置已保存")
}
// 获取表单数据的方法(供父组件调用)
const getFormData = () => {
return [...formDataList.value]
}
// 添加新表单
const addForm = () => {
formDataList.value.push(getDefaultFormData())
ElMessage.primary("已添加新属性配置")
}
// 删除表单
const removeForm = (index: number) => {
if (formDataList.value.length <= 1) {
ElMessage.warning("至少需要保留一个属性配置")
return
}
formDataList.value.splice(index, 1)
ElMessage.warning("已删除属性配置")
}
// 定义暴露给父组件的属性和方法
defineExpose({
getFormData,
saveAllFormData,
addForm,
removeForm
})
onMounted(() => {
initForm()
})
</script>
<style scoped lang="scss">
.prop-form-container {
padding: 20px;
.form-card {
&:last-child {
margin-bottom: 0;
}
.form-card-item {
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
span {
font-weight: bold;
color: #303133;
}
}
.form-content {
:deep(.el-form--inline .el-form-item) {
margin: 0 !important;
}
:deep(.el-form-item) {
margin: 0 !important;
.el-form-item__label {
color: #606266;
font-weight: 500;
}
.form-input,
.form-textarea {
width: 100%;
}
.form-textarea {
min-width: 300px;
}
}
}
}
}
.add-form-button {
display: flex;
gap: 15px;
margin-top: 20px;
justify-content: flex-start;
.save-all-button {
margin-left: 10px;
}
}
}
// 响应式设计
@media (max-width: 768px) {
.prop-form-container {
padding: 10px;
.form-card {
.form-card-item {
.form-content {
:deep(.el-form-item) {
.form-textarea {
min-width: 200px;
}
}
}
}
}
.add-form-button {
flex-direction: column;
.save-all-button {
margin-left: 0;
}
}
}
}
</style>