react-antd表格合并及动态数表头处理

后端数据

说明:monthList: 为动态月份表头标题,data中的valueList 为动态月份对应的动态数据

 const res = {
      monthList: [
        '2023-04',
        '2023-04',
        '2023-05',
        '2023-06',
        '2023-07',
        '2023-08',
        '2023-09',
        '2023-10',
        '2023-11',
        '2023-12',
        '2024-01',
        '2024-02',
        '2024-03',
      ],
      data: [
        {
          partDept: '部门一',
          type: '类型一',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
        {
          partDept: '部门一',
          type: '类型二',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
        {
          partDept: '部门一',
          type: '类型三',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
        {
          partDept: '部门二',
          type: '类型一',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
        {
          partDept: '部门二',
          type: '类型二',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
        {
          partDept: '部门二',
          type: '类型三',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
        {
          partDept: '部门三',
          type: '类型一',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
        {
          partDept: '部门三',
          type: '类型二',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
        {
          partDept: '部门三',
          type: '类型三',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
            { period: '2023-08', value: 100 },
            { period: '2023-09', value: 100 },
            { period: '2023-10', value: 100 },
            { period: '2023-11', value: 100 },
            { period: '2023-12', value: 100 },
            { period: '2024-01', value: 100 },
            { period: '2024-02', value: 100 },
            { period: '2024-03', value: 100 },
          ],
        },
      ],
    };

react代码

import React, { useState, useEffect } from 'react';
import { Col, Row, Table } from 'antd';
import _ from 'lodash';

const Home = () => {
  const [dataList, setDataList] = useState([]);
  const [periodColumns, setPeriodColumns] = useState([]);

  useEffect(() => {
    const res = {
      monthList: ['2023-04', '2023-05', '2023-06', '2023-07'],
      data: [
        {
          partDept: '部门一',
          type: '类型一',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
        {
          partDept: '部门一',
          type: '类型二',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
        {
          partDept: '部门一',
          type: '类型三',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
        {
          partDept: '部门二',
          type: '类型一',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
        {
          partDept: '部门二',
          type: '类型二',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
        {
          partDept: '部门二',
          type: '类型三',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
        {
          partDept: '部门三',
          type: '类型一',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
        {
          partDept: '部门三',
          type: '类型二',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
        {
          partDept: '部门三',
          type: '类型三',
          total: 100,
          valueList: [
            { period: '2023-04', value: 100 },
            { period: '2023-05', value: 100 },
            { period: '2023-06', value: 100 },
            { period: '2023-07', value: 100 },
          ],
        },
      ],
    };

    // 将数据中的动态的valueList打平
    const dataCopy = _.cloneDeep(res.data);
    const newDataList = dataCopy.map((item) => {
      const { valueList } = item;
      const newValueList = valueList.map((it) => {
        return { [it.period]: it.value };
      });
      const list = newValueList.reduce((acc, value) => {
        return { ...acc, ...value };
      });
      return {
        ...item,
        ...list,
      };
    });
    setPeriodColumns(res.monthList);
    setDataList(newDataList);
  }, []);

  // 表头
  const getColumns = () => {
    const columns = [
      {
        title: '部门名称',
        dataIndex: 'partDept',
        width: 150,
        fixed: 'left',
        align: 'center',
        render: (val, record) => ({
          children: <div style={{ fontWeight: 'bold' }}>{val}</div>,
          props: {
            rowSpan: record.rowSpan,
            colSpan: record.colSpan,
          },
        }),
      },
      {
        title: '类型',
        dataIndex: 'type',
        fixed: 'left',
        align: 'center',
        width: 120,
        render: (v) => v,
      },
      {
        title: '汇总',
        dataIndex: 'total',
        align: 'right',
        width: 120,
        render: (v) => v,
      },
    ];
    // 拼接动态表头
    const newPeriodColumns = periodColumns.map((item) => {
      return {
        title: item,
        dataIndex: item,
        align: 'right',
        width: 120,
        render: (v) => v,
      };
    });
    return [...columns, ...newPeriodColumns];
  };

  // 合并单元格处理
  const mergeRows = (rows, key) => {
    rows[0].rowSpan = 1;
    let idx = 0;
    return rows.slice(1).reduce(
      (mergedRows, item, index) => {
        if (item[key] === mergedRows[idx][key]) {
          mergedRows[idx].rowSpan++;
          item.colSpan = 0;
        } else {
          item.rowSpan = 1;
          idx = index + 1;
        }
        return [...mergedRows, item];
      },
      [rows[0]],
    );
  };

  return (
    <div>
      <Row>
        <Col span={24}>
          <Table bordered dataSource={dataList.length > 0 && mergeRows(dataList, 'partDept')}>
            {getColumns().map((item) => {
              return (
                <Table.Column
                  title={item.title}
                  dataIndex={item.dataIndex}
                  fixed={item.fixed}
                  render={item.render}
                  width={item.width}
                  onCell={item.onCell}
                  align={item.align}
                />
              );
            })}
          </Table>
        </Col>
      </Row>
    </div>
  );
};

export default Home;

最终效果

说明: 部门、类型、汇总为固定表头,月份为动态数据,由后端提供
在这里插入图片描述

长表格首次进来可以确定滚动条位置

接上面代码

    // 首次进来时可以确定滚动条的位置 index+1 是因为 汇总, 前提是每列单元格宽度是固定的 本例width为120
    const index = res.monthList.length > 0 && res.monthList.map((item) => item).indexOf('2023-07');
    const element = document.getElementsByClassName('scrollTable')[0];
    const scrollElement = element.getElementsByClassName('ant-table-content')[0];
    scrollElement.scrollLeft = index > 0 ? (index + 1) * 120 : 0;

页面效果

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值