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
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>
|
|
|