前端根据后端数据生成表格 行列合并 指定表头

3 篇文章 0 订阅

封装组件

示例图
在这里插入图片描述

import { nanoid } from "nanoid";
import { cloneElement } from "react";
/*
data 接口返回的数据
headIndex 指定表头的索引
salaryIndex 指定薪资的表头索引
userIndex 指定第一行数据
*/
const SelfTable = ({ data, headIndex, salaryIndex, userIndex }) => {
  const tdLen = data?.lastColNo + 1,
    rows = data?.rows,
    trLen = rows?.length;

  let trData = [];
  for (let i = 0; i < trLen; i++) {
    let tdData = [];
    for (let j = 0; j < tdLen; j++) {
      tdData.push(
        <td width={120} align="center" valign="middle" key={nanoid()}></td>
      );
    }
    trData.push(tdData);
  }
  rows.forEach((itemR, indexR) => {
    const cells = itemR?.cells ?? [],
      cellsLen = cells?.length ?? 0;
    cells.forEach((itemC, indexC) => {
      // 不合并
      if (itemC?.type === 1) {
        trData[indexR][itemC?.col] = (
          <td width={120} align="center" valign="middle" key={nanoid()}>
            {itemC?.value}
          </td>
        );
      } else {
        // 合并
        // 先处理列合并
        if (itemC?.col === itemC?.endCol) {
          trData[indexR][itemC?.col] = (
            <td width={120} align="center" valign="middle" key={nanoid()}>
              {itemC?.value}
            </td>
          );
        } else {
          trData[indexR][itemC?.col] = (
            <td
              width={120}
              align="center"
              valign="middle"
              key={nanoid()}
              colSpan={itemC?.endCol - itemC?.col + 1}
            >
              {itemC?.value}
            </td>
          );
          for (let i = itemC?.col + 1; i <= itemC?.endCol; i++) {
            trData[indexR][i] = "delect";
          }
        }
        // 处理行合并
        if (itemC?.row !== itemC?.endRow && itemC?.endRow) {
          const colItemTd = trData[indexR][itemC?.col];

          trData[indexR][itemC?.col] = cloneElement(colItemTd, {
            rowSpan: itemC?.endRow - itemC?.row + 1,
          });
          if (itemC?.col === itemC?.endCol) {
            for (let i = itemC?.row + 1; i <= itemC?.endRow; i++) {
              trData[i][itemC?.col] = "delect";
            }
          } else {
            for (let i = itemC?.row + 1; i <= itemC?.endRow; i++) {
              for (let j = itemC?.col; j <= itemC?.endCol; j++) {
                trData[i][j] = "delect";
              }
            }
          }
        }
      }
      
      if (indexC === cellsLen - 1) {
        trData[indexR] = trData[indexR]?.filter((item) => item !== "delect");
      }
    });
  });
  trData = trData.reduce((preData, item, index) => {
    item = [
      <td width={120} align="center" valign="middle" key={nanoid()}>
        {index + 1}
      </td>,
      ...item,
    ];
    switch (index) {
      case headIndex:
        item = [
          <td width={120} align="center" valign="middle" key={nanoid()}>
            指定表头了
          </td>,
          ...item,
        ];
        break;
      case salaryIndex:
        item = [
          <td width={120} align="center" valign="middle" key={nanoid()}>
            指定薪资表头了
          </td>,
          ...item,
        ];
        break;
      case userIndex:
        item = [
          <td width={120} align="center" valign="middle" key={nanoid()}>
            设置第一行员工数据
          </td>,
          ...item,
        ];
        break;
      default:
        item = [
          <td width={120} align="center" valign="middle" key={nanoid()}></td>,
          ...item,
        ];
        break;
    }
    return [...preData, <tr key={nanoid()}>{item}</tr>];
  }, []);
  return (
    <table border="1" width="1200" height="600" cellSpacing="0">
      {trData}
    </table>
  );
};
export default SelfTable;


示例数据

export const data = {
  index: 0,
  lastColNo: 8,
  lastRowNo: 15,
  regions: [],
  rows: [
    {
      cells: [
        {
          col: 0,
          colName: "A",
          fillColor: "0",
          refName: "A1",
          row: 0,
          type: 1,
          value: "导入时先预读取第一sheet页前十行内容",
        },
      ],
      lastCol: 0,
      row: 0,
    },
    {
      cells: [
        {
          col: 1,
          colName: "B",
          fillColor: "0",
          refName: "B2",
          row: 1,
          type: 1,
          value: "如果实际内容不到十行,以实际行数为准",
        },
      ],
      lastCol: 1,
      row: 1,
    },
    {
      cells: [
        {
          col: 2,
          colName: "C",
          fillColor: "0",
          refName: "C3",
          row: 2,
          type: 1,
          value:
            "后续优化为,存在多个sheet页时,页面显示当前sheet页名称,并允许切换",
        },
      ],
      lastCol: 2,
      row: 2,
    },
    {
      cells: [
        {
          col: 0,
          colName: "A",
          endCol: 0,
          endRow: 5,
          refName: "A4",
          row: 3,
          type: 2,
          value: "姓名",
        },
        {
          col: 1,
          colName: "B",
          endCol: 1,
          endRow: 5,
          refName: "B4",
          row: 3,
          type: 2,
          value: "手机号",
        },
        {
          col: 2,
          colName: "C",
          endCol: 6,
          endRow: 3,
          refName: "C4",
          row: 3,
          type: 2,
          value: "普通",
        },
        {
          col: 7,
          colName: "H",
          endCol: 7,
          endRow: 5,
          refName: "H4",
          row: 3,
          type: 2,
          value: "银行卡",
        },
        {
          col: 8,
          colName: "I",
          endCol: 8,
          endRow: 5,
          refName: "I4",
          row: 3,
          type: 2,
          value: "开户行",
        },
      ],
      lastCol: 8,
      row: 3,
    },
    {
      cells: [
        {
          col: 2, // 第2列开始 (相当于第三列) 因为是从0开始的
          colName: "C",
          endCol: 4, // 第4列结束 (相当于第五列)  因为是从0开始的
          endRow: 4, // 第4行结束 (相当于第五行) 因为是从0开始的
          refName: "C5",
          row: 4, // 第4行开始 (相当于第五行) 因为是从0开始的
          type: 2, //等于2就是合并,等于1的就是普通单元格不需要合并的
          value: "税前",
        },
        {
          col: 5,
          colName: "F",
          endCol: 5,
          endRow: 5,
          refName: "F5",
          row: 4,
          type: 2,
          value: "个税",
        },
        {
          col: 6,
          colName: "G",
          fillColor: "0",
          refName: "G5",
          row: 4,
          type: 1,
          value: "税后",
        },
      ],
      lastCol: 6,
      row: 4,
    },
    {
      cells: [
        {
          col: 2,
          colName: "C",
          fillColor: "0",
          refName: "C6",
          row: 5,
          type: 1,
          value: "工资",
        },
        {
          col: 3,
          colName: "D",
          fillColor: "0",
          refName: "D6",
          row: 5,
          type: 1,
          value: "奖金",
        },
        {
          col: 4,
          colName: "E",
          fillColor: "0",
          refName: "E6",
          row: 5,
          type: 1,
          value: "应发",
        },
        {
          col: 6,
          colName: "G",
          fillColor: "0",
          refName: "G6",
          row: 5,
          type: 1,
          value: "实发",
        },
      ],
      lastCol: 6,
      row: 5,
    },
    {
      cells: [
        {
          col: 0,
          colName: "A",
          fillColor: "0",
          refName: "A7",
          row: 6,
          type: 1,
          value:
            "这里有可能不是数据,下面内容只是为了便于理解,实际导模板不需要数据",
        },
      ],
      lastCol: 0,
      row: 6,
    },
    {
      cells: [
        {
          col: 0,
          colName: "A",
          fillColor: "0",
          refName: "A8",
          row: 7, //0开始 第7行(8行)的第0列
          type: 1,
          value: "张三",
        },
        {
          col: 1,
          colName: "B",
          fillColor: "0",
          refName: "B8",
          row: 7, //0开始 第7行(8行)的第1列
          type: 1,
          value: 1.3387654321e10,
        },
        {
          col: 2,
          colName: "C",
          fillColor: "0",
          refName: "C8",
          row: 7, //0开始 第7行(8行)的第2列
          type: 1,
          value: 6000.0,
        },
        {
          col: 3,
          colName: "D",
          fillColor: "0",
          refName: "D8",
          row: 7,
          type: 1,
          value: 200.0,
        },
        {
          col: 4,
          colName: "E",
          fillColor: "0",
          formular: "C8+D8",
          refName: "E8",
          row: 7,
          type: 1,
          value: 6200.0,
        },
        {
          col: 5,
          colName: "F",
          fillColor: "0",
          formular: "MAX((E8-5000)*0.3,0)",
          refName: "F8",
          row: 7,
          type: 1,
          value: 360.0,
        },
        {
          col: 6,
          colName: "G",
          fillColor: "0",
          formular: "E8-F8",
          refName: "G8",
          row: 7,
          type: 1,
          value: 5840.0,
        },
        {
          col: 7,
          colName: "H",
          fillColor: "0",
          refName: "H8",
          row: 7,
          type: 1,
          value: "621000123456456461",
        },
        {
          col: 8,
          colName: "I",
          fillColor: "0",
          refName: "I8",
          row: 7,
          type: 1,
          value: "北京银行",
        },
      ],
      lastCol: 8,
      row: 7,
    },
    {
      cells: [
        {
          col: 4,
          colName: "E",
          fillColor: "0",
          formular: "C9+D9",
          refName: "E9",
          row: 8,
          type: 1,
          value: 0.0,
        },
        {
          col: 5,
          colName: "F",
          fillColor: "0",
          formular: "MAX((E9-5000)*0.3,0)",
          refName: "F9",
          row: 8,
          type: 1,
          value: 0.0,
        },
        {
          col: 6,
          colName: "G",
          fillColor: "0",
          formular: "E9-F9",
          refName: "G9",
          row: 8,
          type: 1,
          value: 0.0,
        },
      ],
      lastCol: 6,
      row: 8,
    },
    {
      cells: [
        {
          col: 4,
          colName: "E",
          fillColor: "0",
          formular: "C10+D10",
          refName: "E10",
          row: 9,
          type: 1,
          value: 0.0,
        },
        {
          col: 5,
          colName: "F",
          fillColor: "0",
          formular: "MAX((E10-5000)*0.3,0)",
          refName: "F10",
          row: 9,
          type: 1,
          value: 0.0,
        },
        {
          col: 6,
          colName: "G",
          fillColor: "0",
          formular: "E10-F10",
          refName: "G10",
          row: 9,
          type: 1,
          value: 0.0,
        },
      ],
      lastCol: 6,
      row: 9,
    },
    {
      cells: [
        {
          col: 4,
          colName: "E",
          fillColor: "0",
          formular: "C11+D11",
          refName: "E11",
          row: 10,
          type: 1,
          value: 0.0,
        },
        {
          col: 5,
          colName: "F",
          fillColor: "0",
          formular: "MAX((E11-5000)*0.3,0)",
          refName: "F11",
          row: 10,
          type: 1,
          value: 0.0,
        },
        {
          col: 6,
          colName: "G",
          fillColor: "0",
          formular: "E11-F11",
          refName: "G11",
          row: 10,
          type: 1,
          value: 0.0,
        },
      ],
      lastCol: 6,
      row: 10,
    },
    {
      cells: [
        {
          col: 4,
          colName: "E",
          fillColor: "0",
          formular: "C12+D12",
          refName: "E12",
          row: 11,
          type: 1,
          value: 0.0,
        },
        {
          col: 5,
          colName: "F",
          fillColor: "0",
          formular: "MAX((E12-5000)*0.3,0)",
          refName: "F12",
          row: 11,
          type: 1,
          value: 0.0,
        },
        {
          col: 6,
          colName: "G",
          fillColor: "0",
          formular: "E12-F12",
          refName: "G12",
          row: 11,
          type: 1,
          value: 0.0,
        },
      ],
      lastCol: 6,
      row: 11,
    },
    {
      cells: [
        {
          col: 4,
          colName: "E",
          fillColor: "0",
          formular: "C13+D13",
          refName: "E13",
          row: 12,
          type: 1,
          value: 0.0,
        },
        {
          col: 5,
          colName: "F",
          fillColor: "0",
          formular: "MAX((E13-5000)*0.3,0)",
          refName: "F13",
          row: 12,
          type: 1,
          value: 0.0,
        },
        {
          col: 6,
          colName: "G",
          fillColor: "0",
          formular: "E13-F13",
          refName: "G13",
          row: 12,
          type: 1,
          value: 0.0,
        },
      ],
      lastCol: 6,
      row: 12,
    },
    {
      cells: [
        {
          col: 2,
          colName: "C",
          refName: "C15",
          row: 14,
          type: 1,
          value: "用户数量列数-分组涉及列数=缺少的列数",
        },
      ],
      lastCol: 2,
      row: 14,
    },
    {
      cells: [
        {
          col: 1,
          colName: "B",
          refName: "B16",
          row: 15,
          type: 1,
          value: "过滤",
        },
        {
          col: 2,
          colName: "C",
          refName: "C16",
          row: 15,
          type: 1,
          value: "用户数量列数,分组涉及列数,缺少的列数并按补起分组",
        },
      ],
      lastCol: 2,
      row: 15,
    },
  ],
  sheetName: "Sheet1",
  validations: [],
};

可以通过动态生成表头的方式来实现根据后端返回数据动态渲染多级表头,具体的实现步骤如下: 1. 获取后端返回的表头数据,可以通过 API 接口获取。 2. 遍历表头数据生成对应的列对象。可以使用 Element UI 表格组件中的 column 属性来实现。 3. 如果当前列对象有子列,那么递归生成子列对象。 4. 将生成的列对象数组作为表格组件的 columns 属性进行渲染。 以下是一个示例代码: ```vue <template> <el-table :data="tableData" :columns="tableColumns" border ></el-table> </template> <script> export default { data() { return { tableData: [], tableColumns: [], }; }, methods: { // 获取后端返回的表头数据 async fetchTableHeader() { const res = await fetch('/api/table/header'); const headerData = await res.json(); this.tableColumns = this.generateColumns(headerData); }, // 递归生成列对象 generateColumns(headerData) { return headerData.map((item) => { const column = { label: item.label, prop: item.prop, }; if (item.children && item.children.length) { column.children = this.generateColumns(item.children); } return column; }); }, // 获取后端返回的表格数据 async fetchTableData() { const res = await fetch('/api/table/data'); this.tableData = await res.json(); }, }, mounted() { this.fetchTableHeader(); this.fetchTableData(); }, }; </script> ``` 在这个示例代码中,通过 fetchTableHeader 方法获取后端返回的表头数据,并使用 generateColumns 方法生成对应的列对象,如果当前列对象有子列,那么会递归生成子列对象。最后将生成的列对象数组作为表格组件的 columns 属性进行渲染。 需要注意的是,由于表格数据是异步获取的,因此需要在获取表头数据表格数据之后再进行渲染。在这个示例代码中,通过 mounted 钩子函数来依次调用 fetchTableHeader 和 fetchTableData 方法获取数据,并在获取数据完成后渲染表格组件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值