• 详解和实现数据表格中的行数据合并功能



    theme: smartblue

    前言

    需求场景:

    在提供了数据查看和修改的表格视图中(如table、a-table等…),允许用户自行选择多行数据,依据当前状态进行特定列数据的合并操作。选中的数据将统一显示为选中组的首条数据值。同时,页面会即时反馈显示合并后的效果,提供直观的操作反馈。

    效果

    image.png

    方案选型

    依赖库:vxe-table(:merge-cells="mergeCells"用作效果展示)

    核心逻辑

    根据数据行中的mergeId是否相等判断是否有过合并操作,前端执行合并操作后需将合并的数据的mergeId设置为相同的数值,并将选中数据中需要合并的数据项置为第一行选中的数据,并在页面展示合并后的效果。

    保证两个一致:

    • 数据一致性(数据覆盖) 优先级:极高
    • 展示一致性(根据mergeId调整展示) 优先级:高

    数据源举例

    描述: 常规的后端返回结构,数组对象,数组中每一项指代每一条数据。

    列表数据示例:

    data:[
    {mergeId:1,...},
    {mergeId:2,...},
    {mergeId:3,...}
    ]
    

    合并逻辑:

    - 数据一致性

    coverParams:需要覆盖的参数名,存在于列表数据中

    firstData:第一条数据

    selectRows:选中的数据集合

     coverParams.forEach(item => {
          for (let i = 1; i < number; i++) {
            // 选中的数据都覆盖第一条数据的值
            selectRows[i][item] = firstData[item];
            // }
          }
        });
    
    

    - 展示一致性

    newCurrentRows:由于选择时的随机性和数据结构的不稳定性,记录点击的位置点,并将位置点排序记录。

    // 生成正序数组newCurrentRows
        const newCurrentRows = currentRows.sort((a, b) => a - b);
    // 若newCurrentRows数据不连续 则将选中数据都置为队尾
        const isEqual = newCurrentRows.every((value, index, array) => {
          if (index === 0) {
            return true;
          } else {
            return value === array[index - 1] + 1;
          }
        })
    

    情况1:选中的数据连续

    coverCols:需要合并的行号组,字段的展示位置,用作生成mergeCells

    firstRow:第一行位置

    number:对应rowspan,得到跨几行的数据

    // 获取选中了几条数据
        const number = state.selectRows.length;
      // 取第一个行号
        const firstRow = newCurrentRows[0];
    if (isEqual) {
    const mergeCellsArr = [];
          coverCols.forEach(item => {
            mergeCellsArr.push({
              row: firstRow,
              col: item,
              rowspan: number,
              colspan: 1
            });
          });
          mergeCells.value = mergeCellsArr;
    }
    
    

    情况2:选中的数据不连续

    核心处理:将不连续的数据处理取出放置队尾,满足连续条件继续操作。

          // 非选中的数据
          const fristElements = [];
          // 选中的数据集合
          const secondElements = [];
          // // 选中的数据置于队尾
          // // 遍历原始数组
          const dataNumber = dataSource.value.length;
          for (let i = 0; i < dataNumber; i++) {
            // 如果i在 newCurrentRows中不存在,则将其置于fristElements前列
            if (!newCurrentRows.includes(i)) {
              fristElements.push(dataSource.value[i]);
            }
            // // 如果i在 newCurrentRows中存在,则将其置于fristElements后列
            if (newCurrentRows.includes(i)) {
              secondElements.push(dataSource.value[i]);
            }
          }
          const newSecondElements = secondElements.map(item => {
            return {
              ...item
            };
          });
          // 将新数组的元素追加到原始数组的末尾
          dataSource.value = fristElements.concat(newSecondElements);
    
    

    存在合并标识的数据处理

    主要用作数据中存在mergeId标记如何展示合并效果。

    // 初始数据根据mergeId组装合并效果
      const baseDataMerge = () => {
        // coverCols 需要合并的列号  注塑全新
        const baseCoverCols = getCoverCols();
        // length 需要合并的行数
        const mergedCells = [];
        dataSource.value.forEach((row, rowIndex) => {
          //检查当前行的mergeId是否和下一行的mergeId一样  且mergeId存在
          if (
            rowIndex < dataSource.value.length - 1 &&
            row.mergeId === dataSource.value[rowIndex + 1].mergeId &&
            row.mergeId !== undefined
          ) {
            // 仅在第一次符合条件时 判断横跨几行  默认跨两行
            if (
              dataSource.value[rowIndex + 3] &&
              row.mergeId === dataSource.value[rowIndex + 3].mergeId
            ) {
              // 横跨3行
              state.mergeLength = 4;
            } else if (
              dataSource.value[rowIndex + 2] &&
              row.mergeId === dataSource.value[rowIndex + 2].mergeId
            ) {
              // 横跨4行
              state.mergeLength = 3;
            } else {
              // 横跨2行
              state.mergeLength = 2;
            }
            baseCoverCols.forEach(item => {
              mergedCells.push({
                row: rowIndex, // 开始行,由符合条件的
                rowspan: state.mergeLength, // 合并行数,由选中的数据条数决定
                col: item,
                colspan: 1
              });
            });
            state.mergeFlag = true;
          }
        });
        console.log('初始数据合并效果', mergedCells);
        return mergedCells;
      };
    
  • 相关阅读:
    对象池复用实践
    精读UNSUPERVISED SEMANTIC SEGMENTATION BY DISTILLING FEATURE CORRESPONDENCES
    Jmeter引入外部jar包以满足加密数据的Post请求
    原生js实现移动端京东首页搜索框、菜单栏滑动弹回、倒计时、banner动画、缓慢返回顶部效果(HTML+CSS+JS)
    猿代码浅谈MPI与OpenMP并行程序设计
    cherry-pick
    每日学习——面试题1
    代理现货白银有什么手续
    简单工厂模式
    C语言 数组
  • 原文地址:https://blog.csdn.net/qq_43277404/article/details/139426183