封装table编辑单元格
This commit is contained in:
parent
c973448541
commit
bd219fd37f
|
@ -44,8 +44,8 @@
|
|||
addButtonText?: string
|
||||
removeButtonText?: string
|
||||
userName:string,
|
||||
userPhone:'',
|
||||
userIdCard:''
|
||||
userPhone:string,
|
||||
userIdCard:string
|
||||
}>(), {
|
||||
modelValue: () => [{
|
||||
name: "",
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="toolbar">
|
||||
<n-button @click="handleAdd" type="primary">添加行</n-button>
|
||||
<n-button
|
||||
@click="handleDelete"
|
||||
type="error"
|
||||
:disabled="checkedRowKeys.length === 0"
|
||||
>
|
||||
删除选中
|
||||
</n-button>
|
||||
<n-button @click="toggleSelectMode" type="default">
|
||||
{{ multipleSelect ? '切换单选' : '切换多选' }}
|
||||
</n-button>
|
||||
</div>
|
||||
|
||||
<n-data-table
|
||||
ref="tableRef"
|
||||
:columns="mergedColumns"
|
||||
:data="dataSource"
|
||||
:pagination="false"
|
||||
:row-key="(row: TableRow) => row.id"
|
||||
v-model:checked-row-keys="checkedRowKeys"
|
||||
:checkable="true"
|
||||
:single-line="false"
|
||||
:row-props="rowProps"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, h, computed, defineProps } from 'vue'
|
||||
import type { DataTableColumns, DataTableInst } from 'naive-ui'
|
||||
import { NDataTable, NButton, NInput } from 'naive-ui'
|
||||
|
||||
interface TableRow {
|
||||
id: string
|
||||
[key: string]: any // 支持动态字段
|
||||
}
|
||||
|
||||
interface Props {
|
||||
columns: DataTableColumns<TableRow>
|
||||
initialData?: Record<string, any>[]
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
initialData: () => []
|
||||
})
|
||||
|
||||
// 表格数据
|
||||
const dataSource = ref<TableRow[]>(props.initialData.map(createRow))
|
||||
// 选中行keys
|
||||
const checkedRowKeys = ref<string[]>([])
|
||||
// 是否允许多选
|
||||
const multipleSelect = ref(true)
|
||||
// 表格实例
|
||||
const tableRef = ref<DataTableInst | null>(null)
|
||||
|
||||
// 创建新行
|
||||
function createRow(data: Record<string, any> = {}): TableRow {
|
||||
return {
|
||||
id: Date.now().toString(),
|
||||
...data
|
||||
}
|
||||
}
|
||||
|
||||
// 添加新行
|
||||
const handleAdd = () => {
|
||||
dataSource.value.push(createRow())
|
||||
}
|
||||
|
||||
// 删除选中行
|
||||
const handleDelete = () => {
|
||||
dataSource.value = dataSource.value.filter(
|
||||
(item) => !checkedRowKeys.value.includes(item.id)
|
||||
)
|
||||
checkedRowKeys.value = []
|
||||
}
|
||||
|
||||
// 切换选择模式
|
||||
const toggleSelectMode = () => {
|
||||
multipleSelect.value = !multipleSelect.value
|
||||
checkedRowKeys.value = []
|
||||
}
|
||||
|
||||
// 处理行选择
|
||||
const rowProps = (row: TableRow) => {
|
||||
return {
|
||||
onClick: () => {
|
||||
if (!multipleSelect.value) {
|
||||
checkedRowKeys.value = checkedRowKeys.value.includes(row.id)
|
||||
? []
|
||||
: [row.id]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 合并列配置
|
||||
const mergedColumns = computed<DataTableColumns<TableRow>>(() => {
|
||||
const selectionColumn = {
|
||||
type: 'selection' as const,
|
||||
multiple: multipleSelect.value
|
||||
}
|
||||
|
||||
return [
|
||||
selectionColumn,
|
||||
...props.columns.map(col => {
|
||||
// 如果已经定义 render 方法则直接返回
|
||||
if (col?.render) return col
|
||||
|
||||
// 自动生成可编辑单元格
|
||||
return {
|
||||
...col,
|
||||
render(row: TableRow) {
|
||||
return h(NInput, {
|
||||
value: row[col?.key],
|
||||
onUpdateValue: (value: string) => {
|
||||
row[col?.key] = value
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}) as any
|
||||
]
|
||||
})
|
||||
// 验证函数示例
|
||||
const validateRow = (row: TableRow) => {
|
||||
return props.columns.every(col => {
|
||||
if (col.required) return !!row[col.key]?.toString().trim()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
getTableData: () => dataSource.value,
|
||||
getValidData: () => dataSource.value.filter(validateRow),
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.toolbar {
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
|
@ -24,8 +24,8 @@ const purchaseOrderData:purchaseOrderType[] = [
|
|||
deliveryAddress:'XX大学南门仓库',
|
||||
latestDeliveryTime:'2025-5-22 00:00:00',
|
||||
itemName:'金龙鱼',
|
||||
specifications:'20',
|
||||
itemNumber:'20/5L/桶',
|
||||
specifications:'5L/桶',
|
||||
itemNumber:'20',
|
||||
unitPrice:'¥50',
|
||||
TotalPrice:"¥1000",
|
||||
Remarks:'非转基因'
|
||||
|
@ -39,8 +39,8 @@ const purchaseOrderData:purchaseOrderType[] = [
|
|||
deliveryAddress:'XX大学南门仓库',
|
||||
latestDeliveryTime:'2025-5-22 00:00:00',
|
||||
itemName:'红胡萝卜',
|
||||
specifications:'100斤',
|
||||
itemNumber:'1袋',
|
||||
specifications:'斤',
|
||||
itemNumber:'100',
|
||||
unitPrice:'¥5',
|
||||
TotalPrice:"¥500",
|
||||
Remarks:''
|
||||
|
@ -54,8 +54,8 @@ const purchaseOrderData:purchaseOrderType[] = [
|
|||
deliveryAddress:'XX大学南门仓库',
|
||||
latestDeliveryTime:'2025-5-22 00:00:00',
|
||||
itemName:'苹果',
|
||||
specifications:'100斤',
|
||||
itemNumber:'5箱',
|
||||
specifications:'斤',
|
||||
itemNumber:'100',
|
||||
unitPrice:'¥6',
|
||||
TotalPrice:"¥600",
|
||||
Remarks:''
|
||||
|
|
|
@ -1,9 +1,70 @@
|
|||
<template>
|
||||
<div> 操作日志</div>
|
||||
<div>
|
||||
<editableTable :columns="columns" :initial-data="initialData" ref="initialDataRef"></editableTable>
|
||||
<n-button @click="addEditableTable">确认</n-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="tsx">
|
||||
import editableTable from "@/components/editableTable/index.vue";
|
||||
import { type DataTableColumns } from 'naive-ui'
|
||||
const columns: DataTableColumns<any> = [
|
||||
{
|
||||
title: "切配标准编号",
|
||||
key: "cuttingStandard",
|
||||
// 可自定义验证规则
|
||||
},
|
||||
{
|
||||
title: "预处理要求",
|
||||
key: "pretreatment",
|
||||
// 可自定义验证规则
|
||||
},
|
||||
{
|
||||
title: "切配形状",
|
||||
key: "cutFitShape",
|
||||
// 可自定义验证规则
|
||||
},
|
||||
{
|
||||
title: "切配规格",
|
||||
key: "specifications",
|
||||
// 可自定义验证规则
|
||||
},
|
||||
{
|
||||
title:'包装规格',
|
||||
key:'packaging'
|
||||
},
|
||||
{
|
||||
title: "出成率",
|
||||
key: "yield",
|
||||
// 自定义渲染方式
|
||||
// render(row:any) {
|
||||
// return (
|
||||
// <div>
|
||||
// <n-input value={row.age} on-update-value={(v:number)=>{
|
||||
// row.age = v
|
||||
// }}></n-input>
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
},
|
||||
{
|
||||
title: "切配技法",
|
||||
key: "techniques"
|
||||
// 自动使用默认输入框
|
||||
}
|
||||
];
|
||||
|
||||
const initialData = ref([]);
|
||||
|
||||
const initialDataRef = ref()
|
||||
const addEditableTable = ()=>{
|
||||
if (initialDataRef.value) {
|
||||
const allData = initialDataRef.value.getTableData()
|
||||
const validData = initialDataRef.value.getValidData()
|
||||
console.log('全部数据:', allData)
|
||||
console.log('有效数据:', validData)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
Loading…
Reference in New Issue