element-plus 得table得合并行和列

1,901 阅读1分钟

el-table表格得合并行和列

好久没写了,今天记录一下帮别人做得一个小需求。基于element-plus的table。

一、先展示一下效果吧

image.png

二、上代码

<el-table :data="data" border :span-method="onSpanMethod" style="width: 100%;" height="100%">
    <el-table-column prop="field1" label="field1"></el-table-column>
    <el-table-column prop="field2" label="field2"></el-table-column>
    <el-table-column prop="field3" label="field3"></el-table-column>
    <el-table-column prop="filed4" label="filed4"></el-table-column>
    <el-table-column prop="filed5" label="filed5"></el-table-column>
</el-table>
<script setup lang="ts">
import { spanRow } from "@/utils/tableSpan";
const data = [
  { field1: "营业收费系统", field2: "中国农业银行", field3: "2022-03", filed4: '2022-03-04', filed5: '4' },
  { field1: "营业收费系统", field2: "中国农业银行", field3: "2022-03", filed4: '2022-03-05', filed5: '2' },
  { field1: "营业收费系统", field2: "中国农业银行", field3: "2022-03", filed4: '2022-03-06', filed5: '2' },
  { field1: "营业收费系统", field2: "中国农业银行", field3: "2022-03", filed4: '2022-03-07', filed5: '2' },
  { field1: "营业收费系统", field2: "中国农业银行", field3: "小计", filed4: '', filed5: '2' },
  { field1: "营业收费系统", field2: "中国建设银行", field3: "2022-04", filed4: '2022-04-05', filed5: '3' },
  { field1: "营业收费系统", field2: "中国建设银行", field3: "2022-04", filed4: '2022-04-06', filed5: '2' },
  { field1: "营业收费系统", field2: "中国建设银行", field3: "2022-04", filed4: '2022-04-07', filed5: '2' },
  { field1: "营业收费系统", field2: "中国建设银行", field3: "2022-04", filed4: '2022-04-08', filed5: '2' },
  { field1: "营业收费系统", field2: "中国建设银行", field3: "小计", filed4: '', filed5: '2' },
  { field1: "营业收费系统", field2: "小计", field3: "", filed4: '', filed5: '1' },

  { field1: "报装管理系统", field2: "中国农业银行", field3: "2022-03", filed4: '2022-03-04', filed5: '12' },
  { field1: "报装管理系统", field2: "中国农业银行", field3: "2022-03", filed4: '2022-03-05', filed5: '21' },
  { field1: "报装管理系统", field2: "中国农业银行", field3: "2022-03", filed4: '2022-03-06', filed5: '21' },
  { field1: "报装管理系统", field2: "中国农业银行", field3: "2022-03", filed4: '2022-03-07', filed5: '21' },
  { field1: "报装管理系统", field2: "中国农业银行", field3: "小计", filed4: '', filed5: '6' },
  { field1: "报装管理系统", field2: "中国建设银行", field3: "2022-04", filed4: '2022-04-05', filed5: '11' },
  { field1: "报装管理系统", field2: "中国建设银行", field3: "2022-04", filed4: '2022-04-06', filed5: '53' },
  { field1: "报装管理系统", field2: "中国建设银行", field3: "2022-04", filed4: '2022-04-07', filed5: '53' },
  { field1: "报装管理系统", field2: "中国建设银行", field3: "2022-04", filed4: '2022-04-08', filed5: '53' },
  { field1: "报装管理系统", field2: "中国建设银行", field3: "小计", filed4: '', filed5: '32' },
  { field1: "报装管理系统", field2: "小计", field3: "", filed4: '', filed5: '23' },
]
const option = [
  { index: 0, field: "field1" },
  { index: 1, field: "field2" },
  { index: 2, field: 'field3' }
]
const onSpanMethod = ({ row, column, rowIndex, columnIndex }: any) => {
  return spanRow(
    { row, column, rowIndex, columnIndex },
    data,
    option
  );
}
</script>

主要逻辑就是用的下面这个方法,你可以用一个ts或者js文件封装一下,类型没有规范自己规范一下。

import { watch, computed, unref } from 'vue';
let rowspanArray: any

function spanRow({ row, column, rowIndex, columnIndex }: any, data: any, option: any) {
  if (rowIndex === 0 && columnIndex === 0) {
    computeSpanRow(data, option)
  }
  if ((unref(getCollection(data)) as number[]).includes(rowIndex)) {
    if (columnIndex === 1) {
      return [1, 2]
    } else if (columnIndex > 1 && columnIndex < 3) {
      return [0, 0]
    }
  }
  if (is(option, columnIndex)) {
    const rowspan = rowspanArray[columnIndex][rowIndex]
    const colspan = rowspan > 0 ? 1 : 0

    return {
      rowspan: rowspan,
      colspan: colspan
    }
  }

  return {
    rowspan: 1,
    colspan: 1
  }
}
// 获取分组得个数集合
function getCollection(data: any) {
  return computed(() => {
    const newData: any = {}
    const arr: any = []
    data.forEach((items: any) => {
      let keys: any = items.field1
      if (!newData.hasOwnProperty(items.field1)) {

        newData[keys] = [items]
      } else {
        newData[keys].push(items)
      }
    });
    Object.keys(newData).forEach((res: any, index: number) => {
      if (newData[res].length) {
        if (!arr.length) {
          arr.push(newData[res].length - 1)
        } else {
          arr.push(newData[res].length + arr[arr.length - 1])
        }
      }
    })
    return arr
  })

}

function computeSpanRow(data: any, option: any) {
  rowspanArray = []

  let tempRow = []
  for (let i = 0; i < data.length; i++) {
    for (let j = 0; j < option.length; j++) {
      let index = option[j].index;
      let field = option[j].field;

      if (i === 0) {
        tempRow[index] = 0
        rowspanArray[index] = []
        rowspanArray[index].push(1)
      } else {
        if (data[i][field] === data[i - 1][field]) {
          rowspanArray[index][tempRow[index]] += 1
          rowspanArray[index].push(0)
        } else {
          rowspanArray[index].push(1)
          tempRow[index] = i
        }
      }
    }
  }
}

function is(option: any, index: any) {
  for (let i = 0; i < option.length; i++) {
    if (option[i].index === index) {
      return true
    }
  }
  return false
}

export { spanRow }