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