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

在Angular Material或Highcharts中实现多层嵌套可折叠表格

实现多层嵌套折叠员工报表方案

一、数据重构:平级转树形结构

原始的EmpNTID(员工ID)、RMNTID(上级ID)平级数据无法直接支持嵌套渲染,必须先转成树形结构,每个节点包含自身信息和下属数组。

重构代码示例(TypeScript)

// 定义原始员工数据结构
interface RawEmployee {
  empNTID: string;
  rmNTID: string;
  name: string;
  // 其他业务字段(如部门、职位等)
}

// 定义树形节点结构
interface EmployeeTreeNode extends RawEmployee {
  children: EmployeeTreeNode[];
}

// 从平级数据构建树形结构
function buildEmployeeTree(rawData: RawEmployee[], rootEmpNTID: string): EmployeeTreeNode {
  // 用Map快速查找节点
  const nodeMap = new Map<string, EmployeeTreeNode>();
  
  // 先将所有员工转为树形节点,存入Map
  rawData.forEach(emp => {
    nodeMap.set(emp.empNTID, { ...emp, children: [] });
  });
  
  // 遍历数据,将每个员工挂载到对应上级的children数组中
  rawData.forEach(emp => {
    if (emp.rmNTID && nodeMap.has(emp.rmNTID)) {
      nodeMap.get(emp.rmNTID)!.children.push(nodeMap.get(emp.empNTID)!);
    }
  });
  
  // 返回根节点(即Carmen对应的EmpNTID)
  return nodeMap.get(rootEmpNTID)!;
}

二、Angular Material 实现多层折叠表格/层级列表

优先用Angular Material的mat-expansion-panel结合递归组件实现,天然支持多层嵌套折叠,完全符合需求。

1. 创建递归子组件(employee-tree-node.component)

这个组件负责渲染单个员工节点,同时递归渲染其下属:

组件模板(employee-tree-node.component.html)

<mat-expansion-panel [expanded]="false">
  <mat-expansion-panel-header>
    <mat-panel-title>
      {{ node.name }} ({{ node.empNTID }})
    </mat-panel-title>
    <mat-panel-description>
      {{ node.position }} | {{ node.department }}
    </mat-panel-description>
  </mat-expansion-panel-header>
  
  <!-- 显示当前员工的详细信息(表格行形式) -->
  <div class="employee-details">
    <table mat-table [dataSource]="[node]" class="mat-elevation-z1">
      <ng-container matColumnDef="empNTID">
        <th mat-header-cell *matHeaderCellDef>员工ID</th>
        <td mat-cell *matCellDef="let emp">{{ emp.empNTID }}</td>
      </ng-container>
      <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef>姓名</th>
        <td mat-cell *matCellDef="let emp">{{ emp.name }}</td>
      </ng-container>
      <ng-container matColumnDef="department">
        <th mat-header-cell *matHeaderCellDef>部门</th>
        <td mat-cell *matCellDef="let emp">{{ emp.department }}</td>
      </ng-container>
      
      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
  </div>
  
  <!-- 递归渲染下属节点 -->
  <app-employee-tree-node 
    *ngFor="let child of node.children" 
    [node]="child">
  </app-employee-tree-node>
</mat-expansion-panel>

组件类(employee-tree-node.component.ts)

import { Component, Input } from '@angular/core';
import { EmployeeTreeNode } from '../models/employee.model';

@Component({
  selector: 'app-employee-tree-node',
  templateUrl: './employee-tree-node.component.html',
  styleUrls: ['./employee-tree-node.component.scss']
})
export class EmployeeTreeNodeComponent {
  @Input() node!: EmployeeTreeNode;
  displayedColumns: string[] = ['empNTID', 'name', 'department'];
}

2. 父组件调用(根组件)

在父组件中加载原始数据,构建树形结构后,渲染根节点(Carmen):

父组件模板(app.component.html)

<div class="container">
  <h2>层级员工报表</h2>
  <app-employee-tree-node [node]="rootEmployee"></app-employee-tree-node>
</div>

父组件类(app.component.ts)

import { Component, OnInit } from '@angular/core';
import { RawEmployee, EmployeeTreeNode, buildEmployeeTree } from './models/employee.model';
// 假设从API获取数据,这里用模拟数据示例
const mockRawData: RawEmployee[] = [
  { empNTID: 'Carmen001', rmNTID: null, name: 'Carmen', department: '总部', position: 'CEO' },
  { empNTID: 'Bob001', rmNTID: 'Carmen001', name: 'Bob', department: '研发部', position: '研发经理' },
  { empNTID: 'Alice001', rmNTID: 'Bob001', name: 'Alice', department: '研发部', position: '前端开发' },
  // 更多员工数据...
];

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  rootEmployee!: EmployeeTreeNode;

  ngOnInit(): void {
    // 构建树形结构,传入Carmen的EmpNTID
    this.rootEmployee = buildEmployeeTree(mockRawData, 'Carmen001');
  }
}

三、关于Highcharts的说明

Highcharts核心是图表组件,并不擅长实现嵌套表格的折叠功能,不符合你“表格形式呈现”的需求,因此不建议用Highcharts实现该功能。

四、关键注意事项

  • 确保原始数据中顶层员工(Carmen)的RMNTID为null或唯一标识(如空字符串),避免构建树形结构时出错。
  • 如果员工数量较多,可考虑添加懒加载:点击展开时再请求该员工的下属数据,而非一次性构建完整树形结构。

内容的提问来源于stack exchange,提问作者FlyFish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 03:33:15