封装table编辑单元格

This commit is contained in:
wangyilin 2025-05-20 14:47:55 +08:00
parent c973448541
commit bd219fd37f
4 changed files with 218 additions and 10 deletions

View File

@ -44,8 +44,8 @@
addButtonText?: string addButtonText?: string
removeButtonText?: string removeButtonText?: string
userName:string, userName:string,
userPhone:'', userPhone:string,
userIdCard:'' userIdCard:string
}>(), { }>(), {
modelValue: () => [{ modelValue: () => [{
name: "", name: "",

View File

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

View File

@ -24,8 +24,8 @@ const purchaseOrderData:purchaseOrderType[] = [
deliveryAddress:'XX大学南门仓库', deliveryAddress:'XX大学南门仓库',
latestDeliveryTime:'2025-5-22 00:00:00', latestDeliveryTime:'2025-5-22 00:00:00',
itemName:'金龙鱼', itemName:'金龙鱼',
specifications:'20', specifications:'5L/桶',
itemNumber:'20/5L/桶', itemNumber:'20',
unitPrice:'¥50', unitPrice:'¥50',
TotalPrice:"¥1000", TotalPrice:"¥1000",
Remarks:'非转基因' Remarks:'非转基因'
@ -39,8 +39,8 @@ const purchaseOrderData:purchaseOrderType[] = [
deliveryAddress:'XX大学南门仓库', deliveryAddress:'XX大学南门仓库',
latestDeliveryTime:'2025-5-22 00:00:00', latestDeliveryTime:'2025-5-22 00:00:00',
itemName:'红胡萝卜', itemName:'红胡萝卜',
specifications:'100斤', specifications:'斤',
itemNumber:'1', itemNumber:'100',
unitPrice:'¥5', unitPrice:'¥5',
TotalPrice:"¥500", TotalPrice:"¥500",
Remarks:'' Remarks:''
@ -54,8 +54,8 @@ const purchaseOrderData:purchaseOrderType[] = [
deliveryAddress:'XX大学南门仓库', deliveryAddress:'XX大学南门仓库',
latestDeliveryTime:'2025-5-22 00:00:00', latestDeliveryTime:'2025-5-22 00:00:00',
itemName:'苹果', itemName:'苹果',
specifications:'100斤', specifications:'斤',
itemNumber:'5箱', itemNumber:'100',
unitPrice:'¥6', unitPrice:'¥6',
TotalPrice:"¥600", TotalPrice:"¥600",
Remarks:'' Remarks:''

View File

@ -1,9 +1,70 @@
<template> <template>
<div> 操作日志</div> <div>
<editableTable :columns="columns" :initial-data="initialData" ref="initialDataRef"></editableTable>
<n-button @click="addEditableTable">确认</n-button>
</div>
</template> </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> </script>
<style scoped lang="scss"> <style scoped lang="scss">