封装table编辑单元格
This commit is contained in:
parent
c973448541
commit
bd219fd37f
|
@ -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: "",
|
||||||
|
|
|
@ -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大学南门仓库',
|
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:''
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in New Issue