NG-ZORRO + angular-cli11 表格横纵向单元格合并,按需设置背景色,解决动态合并单元格动态colspan情况下,nzLeft固定列失效问题,也适用VUE,REACT

NG-ZORRO + angular-cli11 实现表格横纵向单元格合并,按需设置背景色,并解决动态合并单元格动态colspan情况下,nzLeft固定列失效问题


HTML代码

<!-- 
  1.发现只要colspan只要是动态的,nzleft就不正常了,无法起作用 
  2.合并单元格且固定列位置方案1:比如标题,可以固定一部分,然后另外一部分不固定
  3.合并单元格且固定列位置方案2:可以动态设置其样式
-->
<div class="my-table">

  <nz-table #colSpanTable  nzBordered
  [nzScroll]="{ x: (tableObj.arr.length+3)*95+'px', y: '240px' }" [nzFrontPagination]="false">
  <thead>
    <tr nzLeft>
      <!-- 方案1 -->
      <th colspan="3" nzLeft style="border-right: 0px">{{tableObj.ss}}</th>
      <th [colspan]="tableObj.arr.length"></th>
      <!-- 方案1 -->
    </tr>
    <tr>
      <th [colspan]="3" nzLeft id="my_hr_table_title">左侧合并小标题</th>
      <th *ngFor="let item of tableObj.arr; index as i">{{item}}</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let item of tableData;">
      <td colspan="3" nzLeft>{{ item.type }}</td>
      <td *ngFor="let innerItem of item.Content;">{{innerItem.name}}</td>
    </tr>
    <tr *ngFor="let item of table02">
      <ng-container *ngFor="let t of mergeColumns; index as i">
        <ng-container *ngIf="item[t]!==undefined">
          <!-- 方案2 -->
          <td [attr.rowspan]="item[mergeFix+t]" class="ant-table-cell-fix-left" [style]="getStyle(i)">{{ item[t] }}
          </td>
          <!-- 方案2 -->
        </ng-container>
      </ng-container>
      <td class="ant-table-cell-fix-left" [style]="getStyle(2)">{{item.key03}}</td>
      <td *ngFor="let innerItem of item.Content" [ngClass]="getClass(innerItem.color)">{{innerItem.name}}</td>
    </tr>
  </tbody>
</nz-table>
</div>

TS 代码

import { Component, OnInit } from '@angular/core'

@Component({
  selector: 'table-report',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.less'],
})
export class MyTableComponent implements OnInit {
  constructor() {}
  tableObj = {
    ss: '合并单元格的大标题',
    arr: ['item1', 'item13', 'item14', 'item107', 'item101', 'item102', 'item103', 'item104', 'item105', 'item106']
  }
  tableData = [
    {
      type: '横向合并第一列',
      Content: [
        {
          name: 'ha11'
        },
        {
          name: 'ha12'
        },
        {
          name: 'ha13'
        },
        {
          name: 'ha14'
        },
        {
          name: 'ha15'
        },
        {
          name: 'ha16'
        },
        {
          name: 'ha17'
        },
        {
          name: 'ha18'
        },
        {
          name: 'ha19'
        },
        {
          name: 'ha20'
        },
      ]
    },
    {
      type: '横向合并第2列',
      Content: [
        {
          name: 'ha11'
        },
        {
          name: 'ha12'
        },
        {
          name: 'ha13'
        },
        {
          name: 'ha14'
        },
        {
          name: 'ha15'
        },
        {
          name: 'ha16'
        },
        {
          name: 'ha17'
        },
        {
          name: 'ha18'
        },
        {
          name: 'ha19'
        },
        {
          name: 'ha20'
        }
      ]
    }
  ]
  table02: any = [];
  tableData2 = [
    {
      // 需要加上这一个东西
      key: '0',
      ll: '第三列01',
      LineMergerRow: 12,
      ss: '第三列02', // 需要加上这一个东西
      StationMergerRow: 3,
      key03: '第三列03', // 需要加上这一个东西
      ClassOrder: 1,
      Content: [
        {
          name: 'bottom01',
        },
        {
          name: 'bottom012',
        },
        {
          name: 'bottom013',
        },
        {
          name: 'bottom014',
        },
        {
          name: 'bottom015',
        },
        {
          name: 'bottom016',
        },
        {
          name: 'bottom017',
        },
        {
          name: 'bottom018',
        },
        {
          name: 'bottom019',
        },
        {
          name: 'bottom0120',
        },
      ],
    },
    {
      key: '2',
      ll: '根据LL自动合并的数据',
      LineMergerRow: 12,
      ss: 'CCC',
      StationMergerRow: 3,
      key03: '不需要合并',
      ClassOrder: 1,
      Content: [
        {
          name: 'color1',
          color: 1,
        },
        {
          name: 'color1',
          color: 2,
        },
        {
          name: 'color1',
          color: 3,
        },
        {
          name: 'color1',
          color: 4,
        },
        {
          name: 'color1',
          color: 4,
        },
        {
          name: 'color1',
          color: 1,
        },
        {
          name: 'color1',
          color: 2,
        },
        {
          name: 'color1',
          color: 3,
        },
        {
          name: 'color1',
          color: 4,
        },
        {
          name: 'color1',
          color: 4,
        },
      ],
    },
    {
      key: '3',
      ll: '根据LL自动合并的数据',
      LineMergerRow: 12,
      ss: '根据SS自动合并',
      StationMergerRow: 3,
      key03: '不需要合并',
      ClassOrder: 2,
      Content: [
        {
          name: 'color1',
          color: 0,
        },
        {
          name: 'color1',
          color: 1,
        },
        {
          name: 'color1',
          color: 2,
        },
        {
          name: 'color1',
          color: 3,
        },
        {
          name: 'color1',
          color: 4,
        },
        {
          name: 'color1',
          color: 4,
        },
        {
          name: 'color1',
          color: 3,
        },
        {
          name: 'color1',
          color: 0,
        },
        {
          name: 'color1',
          color: 2,
        },
        {
          name: 'color1',
          color: 0,
        },
      ],
    },

    {
      key: '4',
      ll: '根据LL自动合并的数据',
      LineMergerRow: 12,
      ss: '根据SS自动合并',
      StationMergerRow: 3,
      key03: '不需要合并3',
      ClassOrder: 3,
      Content: [
        {
          name: 'color1',
          color: 3,
        },
        {
          name: 'color1',
          color: 0,
        },
        {
          name: 'color1',
          color: 2,
        },
        {
          name: 'color1',
          color: 0,
        },
        {
          name: 'color1',
          color: 3,
        },
        {
          name: 'color1',
          color: 0,
        },
        {
          name: 'color1',
          color: 2,
        },
        {
          name: 'color1',
          color: 0,
        },
        {
          name: 'color1',
          color: 3,
        },
        {
          name: 'color1',
          color: 0,
        },
      ],
    },
  ];

  mergeFix = 'mergeFlag'
  mergeColumns = ['ll', 'ss']; // 合并列的键值
  ngOnInit(): void {
    this.table02 = this.sortAndMerge(this.tableData2);
  }

  /**
   * 自动合并单元格的方法
   * @param rawDataList 需要合并数据的数组
   */
  private sortAndMerge(rawDataList): any[] {
    const rowspan = this.mergeFix,
      mergeColumns = this.mergeColumns;
    if (rawDataList.length > 1) {
      //长度大于1才有资格进一步处理
      const sortColumn = Object.keys(rawDataList[0]),
        keySort = (raw) => {
          for (let i = raw.length - 1; i > 0; i--) {
            let newObj = {},
              tmpObj = raw[i];
            sortColumn.forEach((s) => (newObj[s] = tmpObj[s]));
            raw[i] = newObj;
          }
          return raw;
        },
        compare = (a, b, c = sortColumn[0], i = 0) => {
          if (a[c] === b[c]) {
            //等于的话进行判断是否还有后续字段需要排序,没有则返回0;有则递归进行后续字段排序处理。
            if (i === sortColumn.length - 1) {
              //没有后续字段
              return (i = 0);
            }
            i++;
            return compare(a, b, sortColumn[i], i); //递归排序后续字段
          } else if (a[c] > b[c]) {
            //大于返回1
            return 1;
          } else {
            //小于返回-1
            return -1;
          }
        },
        arr = keySort(JSON.parse(JSON.stringify(rawDataList))).sort(compare),
        aLen = arr.length;
      for (let i = mergeColumns.length - 1; i >= 0; i--) {
        //先迭代待合并列
        let index = 0;
        let title = mergeColumns[i];
        let span = 1; //合并列属性默认为1
        for (let j = 0; j < aLen; j++) {
          let comp = arr[index][title];
          if (arr[j][title] === comp) {
            j !== index && (delete arr[j][title], span++);
            console.log(rowspan);
            j === aLen - 1 && (arr[index][rowspan + title] = span);
          } else {
            span > 1 && ((arr[index][rowspan + title] = span), (span = 1));
            index = j;
          }
        }
      }
      return arr;
    }
    return rawDataList;
  }
  getClass(e) {
    return { 0: 'col-green', 1: 'col-light-green', 2: 'col-orange', 3: 'col-red' }[e] || 'col-beautiful-green'
  }
  getStyle(e) {
    return (
      { 0: 'position: sticky; left: 0px;', 1: 'position: sticky; left: 95px;', 2: 'position: sticky; left: 190px;' }[e] ||
      'position: sticky; left: 0px;'
    );
  }
}

less 代码

// 僅供測試階段使用
::ng-deep .alain-default__fixed .alain-default__aside {
  display: none;
}
::ng-deep .alain-default__content {
  margin-left: 20px;
}
// 僅供測試階段使用
.my-table {
  margin-top: 30px;
  color: rgb(0, 0, 0);
  // 减小间距
  /deep/.ant-table-thead > tr > th {
    padding-bottom: 5px;
    padding-top: 5px;
    color: rgb(0, 0, 0);
  }
  /deep/.ant-table-tbody > tr > td {
    padding: 5px 4px;
    color: rgb(0, 0, 0);
  }
  // 减小间距
  /deep/.ant-table {
    color: rgb(0, 0, 0);
}
  .col-green {
    background: green;
  }
  .col-light-green {
    background: rgb(185, 233, 185);
  }
  .col-orange {
    background: orange;
  }
  .col-red {
    background: red;
  }
  .col-beautiful-green {
    background: rgb(234, 250, 234);
  }
  .my_item {
    min- 600px;
    padding: 0 10px 0 10px;
     50%;
    display: inline-block;
  }
}
原文地址:https://www.cnblogs.com/sugartang/p/14847537.html