You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

151 lines
3.3 KiB

<template>
<div>
<Table
:columns="columns"
:dataSource="dataSource"
:bordered="true"
:pagination="false"
>
<template #bodyCell="{ column, record, index }">
<template v-if="column.dataIndex === 'name'">
<Form.Item
:validateStatus="!record.name ? 'error' : ''"
:help="!record.name ? '产品名称为必填项' : ''"
class="compact-form-item"
>
<Input v-model:value="record.name" placeholder="请输入名称" />
</Form.Item>
</template>
<template v-if="column.dataIndex === 'model'">
<Input v-model:value="record.model" placeholder="请输入型号" />
</template>
<template v-if="column.dataIndex === 'versionStr'">
<Input v-model:value="record.versionStr" placeholder="请输入版本" />
</template>
<template v-if="column.key === 'operation'">
<Button type="link" @click="handleDelete(index)">删除</Button>
</template>
</template>
</Table>
<Button type="primary" @click="handleAdd" style="margin-top: 16px">新增</Button>
</div>
</template>
<script setup lang="ts">
import { ref, defineExpose } from 'vue'
import { Table, Input, Button, Form } from 'ant-design-vue'
import { message } from 'ant-design-vue'
interface TableItem {
key: string
name: string
model: string
versionStr: string
}
const columns = [
{
title: '产品名称必填',
dataIndex: 'name',
key: 'name',
width: '33%',
rules: [{ required: true, message: '名称为必填项' }]
},
{
title: '型号',
dataIndex: 'model',
key: 'model',
width: '33%'
},
{
title: '版本',
dataIndex: 'versionStr',
key: 'versionStr',
width: '33%'
},
{
title: '操作',
key: 'operation',
width: 80,
},
]
const dataSource = ref<TableItem[]>([])
// 添加验证方法
const validate = () => {
const emptyNameItems = dataSource.value.filter(item => !item.name);
if (emptyNameItems.length > 0) {
message.error('请填写所有行的名称');
return false;
}
return true;
}
const handleAdd = () => {
// 检查已有数据是否都填写了必填项
for (const item of dataSource.value) {
if (!item.name) {
message.error('请先填写已有行的名称')
return
}
}
dataSource.value.push({
key: Date.now().toString(),
name: '',
model: '',
versionStr: ''
})
}
const getData = () => {
return dataSource.value
}
// 添加设置数据方法
const setData = (data: TableItem[]) => {
if (!data || data.length === 0) {
dataSource.value = []
return
}
// 为每条数据添加key
const formattedData = data.map(item => ({
...item,
key: item.key || Date.now().toString()
}))
dataSource.value = formattedData
}
// 删除行方法
const handleDelete = (index: number) => {
if (dataSource.value.length <= 1) {
message.warning('至少保留一行数据');
return;
}
dataSource.value.splice(index, 1);
}
defineExpose({
getData,
validate,
setData
})
</script>
<style scoped>
.compact-row :deep(.ant-form-item) {
margin-bottom: 0;
}
.compact-form-item {
margin-bottom: 0 !important;
}
:deep(.ant-table-tbody > tr > td) {
padding: 8px;
}
</style>