You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular中垂直填充表格?基于NG Zorro实现MITRE矩阵展示

需求与问题

我需要在前端用表格展示MITRE矩阵,后端返回的数据包含每个战术下的工单数量等信息,要求表格按列垂直填充(即一列对应一个技术,该列从上到下依次显示该技术下的所有战术),但目前用NG Zorro写的代码只能填充单列,无法实现多列垂直布局。

后端返回的核心数据结构如下:

"tableData": [
    {
        "technique": "Reconnaissance",
        "tactics": [
            {"tactic": "Active Scanning", "id": "T1595", "total_tickets": 14},
            {"tactic": "Gather Victim Host Information", "id": "T1592", "total_tickets": 0},
            {"tactic": "Gather Victim Identity Information", "id": "T1589", "total_tickets": 0},
            {"tactic": "Gather Victim Network Information", "id": "T1590", "total_tickets": 0},
            {"tactic": "Gather Victim Org Information", "id": "T1591", "total_tickets": 2},
            {"tactic": "Phishing for Information", "id": "T1598", "total_tickets": 1},
            {"tactic": "Search Closed Sources", "id": "T1597", "total_tickets": 0},
            {"tactic": "Search Open Technical Databases", "id": "T1596", "total_tickets": 0},
            {"tactic": "Search Open Websites/Domains", "id": "T1593", "total_tickets": 0},
            {"tactic": "Search Victim-Owned Websites", "id": "T1594", "total_tickets": 1}
        ]
    },
    {
        "technique": "Resource Development",
        "tactics": [
            {"tactic": "Acquire Infrastructure", "id": "T1583", "total_tickets": 1},
            {"tactic": "Compromise Accounts", "id": "T1586", "total_tickets": 1},
            {"tactic": "Compromise Infrastructure", "id": "T1584", "total_tickets": 5},
            {"tactic": "Develop Capabilities", "id": "T1587", "total_tickets": 4},
            {"tactic": "Establish Accounts", "id": "T1585", "total_tickets": 0},
            {"tactic": "Obtain Capabilities", "id": "T1588", "total_tickets": 2},
            {"tactic": "Stage Capabilities", "id": "T1608", "total_tickets": 0}
        ]
    },
    {
        "technique": "Initial Access",
        "tactics": [
            {"tactic": "Drive-by Compromise", "id": "T1189", "total_tickets": 1},
            {"tactic": "Exploit Public-Facing Application", "id": "T1190", "total_tickets": 2},
            {"tactic": "External Remote Services", "id": "T1133", "total_tickets": 0},
            {"tactic": "Hardware Additions", "id": "T1200", "total_tickets": 0},
            {"tactic": "Phishing", "id": "T1566", "total_tickets": 2},
            {"tactic": "Replication Through Removable Media", "id": "T1091", "total_tickets": 1},
            {"tactic": "Supply Chain Compromise", "id": "T1195", "total_tickets": 0},
            {"tactic": "Trusted Relationship", "id": "T1199", "total_tickets": 0},
            {"tactic": "Valid Accounts", "id": "T1078", "total_tickets": 8}
        ]
    }
]

当前使用NG Zorro的表格代码(仅能填充单列):

<div class="simple-card">
  <div class="table-header flex between wrap">
    <div class="card-title">
      <span *ngIf="isLoading">Cargando...</span>
      <span *ngIf="!isLoading">{{totalData || 0}} {{title || ''}}</span>
    </div>
  </div>

  <div class="table-container">
    <nz-table #basicTable
              [nzShowPagination]="false"
              [nzTotal]="totalData"
              [nzLoading]="isLoading"
              [nzBordered]="true"
              [nzData]="data">
      <thead>
        <tr>
          <th *ngFor="let technique of basicTable.data">{{technique.technique}}</th>
        </tr>
      </thead>
      <tbody>
      <ng-container *ngFor="let techniqueObject of basicTable.data">
        <tr *ngFor="let tacticObject of techniqueObject.tactics">
          <td>{{tacticObject.tactic}}: {{tacticObject.total_tickets}}</td>
        </tr>
      </ng-container>
      </tbody>
    </nz-table>
  </div>
</div>
解决方案

要实现按列垂直填充,需要先转换数据结构,再修改模板渲染逻辑:

1. 组件内转换数据

首先找到所有技术中战术数量的最大值,生成对应行数的数组,每行包含对应位置的各技术战术数据(战术数量不足的技术补空结构)。

在组件的TypeScript代码中添加数据转换逻辑:

// 假设后端返回的数据存储在tableData变量中
transformedData: any[] = [];

ngOnInit(): void {
  // 提取所有技术的战术列表
  const tacticsLists = this.tableData.map(item => item.tactics);
  // 计算最长战术列表长度,确定表格总行数
  const maxRows = Math.max(...tacticsLists.map(list => list.length));
  
  // 构建转换后的数据:每行对应表格的一行,每行元素对应各列的战术数据
  for (let i = 0; i < maxRows; i++) {
    const row = this.tableData.map(tech => {
      return tech.tactics[i] || { tactic: '', total_tickets: 0 };
    });
    this.transformedData.push(row);
  }
}

2. 修改NG Zorro表格模板

将表格数据源替换为转换后的transformedData,调整表头和表体的渲染逻辑:

<div class="simple-card">
  <div class="table-header flex between wrap">
    <div class="card-title">
      <span *ngIf="isLoading">加载中...</span>
      <span *ngIf="!isLoading">{{totalData || 0}} {{title || ''}}</span>
    </div>
  </div>

  <div class="table-container">
    <nz-table #basicTable
              [nzShowPagination]="false"
              [nzTotal]="totalData"
              [nzLoading]="isLoading"
              [nzBordered]="true"
              [nzData]="transformedData">
      <thead>
        <tr>
          <!-- 表头直接使用原数据中的技术名称 -->
          <th *ngFor="let tech of tableData">{{tech.technique}}</th>
        </tr>
      </thead>
      <tbody>
        <!-- 每行渲染对应列的战术信息 -->
        <tr *ngFor="let row of basicTable.data">
          <td *ngFor="let tactic of row">
            <span *ngIf="tactic.tactic">{{tactic.tactic}}: {{tactic.total_tickets}}</span>
          </td>
        </tr>
      </tbody>
    </nz-table>
  </div>
</div>

说明

  • 数据转换后,transformedData的每一项对应表格的一行,每行元素对应各列的战术数据,确保每列垂直填充对应技术的所有战术。
  • 对于战术数量较少的技术,空白位置会显示空内容,可根据需求自定义占位文本。
  • 表头直接绑定原tableData的技术名称,保证列数与技术的对应关系正确。

内容的提问来源于stack exchange,提问作者Jair León

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 04:39:26