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

Highcharts Gantt:垂直分组任务并包含分组子任务的实现问题

Highcharts Gantt 折叠子行数据丢失问题解决方案

问题场景

使用Highcharts Gantt模块创建时间线活动图表时,需实现两个需求:

  • 单个分类行显示多个时间范围
  • 该行包含带分组数据的子行

单独实现每个需求均正常,但结合后执行折叠操作会导致数据丢失,推测是ID重复导致。

问题代码示例

const today = new Date(),
      day = 1000 * 60 * 60 * 24;

// 重置为当天00:00:00.000
today.setUTCHours(0);
today.setUTCMinutes(0);
today.setUTCSeconds(0);
today.setUTCMilliseconds(0);

// 初始化图表
Highcharts.ganttChart('container', {
    title: {
        text: 'Highcharts Gantt with Nested Subtasks'
    },
    xAxis: {
        min: today.getTime() - (2 * day),
        max: today.getTime() + (32 * day)
    },
    yAxis: {
        uniqueNames: true
    },
    series: [{
        name: 'Project 1',
        data: [{
            name: 'Planning',
            id: 'planning',
            start: today.getTime(),
            end: today.getTime() + (20 * day)
        }, {
            name: 'Requirements',
            id: 'requirements',
            parent: 'planning',
            start: today.getTime(),
            end: today.getTime() + (5 * day)
        }, {
            name: 'Design',
            id: 'design',
            dependency: 'requirements',
            parent: 'planning',
            start: today.getTime() + (3 * day),
            end: today.getTime() + (20 * day)
        }, {
            name: 'Layout',
            id: 'layout',
            start: today.getTime() + (3 * day),
            end: today.getTime() + (10 * day)
        }, 
        {    
            name: 'Layout',
            id: 'layout',
            start: today.getTime() + (15 * day),
            end: today.getTime() + (18 * day)
        },
        {
            name: 'Layout Task',
            parent: 'layout',
            start: today.getTime() + (3 * day),
            end: today.getTime() + (5 * day)
        }, {
            name: 'Layout Task',
            parent: 'layout',
            start: today.getTime() + (5 * day),
            end: today.getTime() + (7 * day)
        }, {
            name: 'Layout Task',
            parent: 'layout',
            start: today.getTime() + (7 * day),
            end: today.getTime() + (10 * day)
        }, {
            name: 'Graphics',
            parent: 'design',
            start: today.getTime() + (10 * day),
            end: today.getTime() + (20 * day)
        }]
    }]
})

问题根源

代码中存在重复ID:两个Layout时间任务共用id: 'layout',而Highcharts Gantt通过唯一ID关联父子节点。折叠时仅能识别第一个ID对应的任务,第二个任务因ID重复无法被正确关联,最终导致数据丢失。

修复方案

1. 分配唯一ID

确保所有数据点的id不重复,比如将第二个Layout任务的ID设为layout-2。

2. 统一父节点结构

创建一个顶级Layout分组容器(仅作为折叠父节点,可省略start/end),将两个时间任务和子任务都挂在该容器下,确保折叠操作能覆盖所有关联项。

3. 控制同一行显示

通过yAxis.uniqueNames: true,设置相同name让多个任务自动显示在同一行,或手动指定相同y值。

修复后的代码示例

const today = new Date(),
      day = 1000 * 60 * 60 * 24;

today.setUTCHours(0, 0, 0, 0);

Highcharts.ganttChart('container', {
    title: {
        text: 'Highcharts Gantt with Nested Subtasks'
    },
    xAxis: {
        min: today.getTime() - (2 * day),
        max: today.getTime() + (32 * day)
    },
    yAxis: {
        uniqueNames: true
    },
    series: [{
        name: 'Project 1',
        data: [{
            name: 'Planning',
            id: 'planning',
            start: today.getTime(),
            end: today.getTime() + (20 * day)
        }, {
            name: 'Requirements',
            id: 'requirements',
            parent: 'planning',
            start: today.getTime(),
            end: today.getTime() + (5 * day)
        }, {
            name: 'Design',
            id: 'design',
            dependency: 'requirements',
            parent: 'planning',
            start: today.getTime() + (3 * day),
            end: today.getTime() + (20 * day)
        }, {
            // 顶级Layout分组容器,仅用于折叠控制
            name: 'Layout',
            id: 'layout-group'
        }, {
            name: 'Layout',
            id: 'layout-1',
            parent: 'layout-group',
            start: today.getTime() + (3 * day),
            end: today.getTime() + (10 * day)
        }, {    
            name: 'Layout',
            id: 'layout-2',
            parent: 'layout-group',
            start: today.getTime() + (15 * day),
            end: today.getTime() + (18 * day)
        }, {
            name: 'Layout Task',
            parent: 'layout-group',
            start: today.getTime() + (3 * day),
            end: today.getTime() + (5 * day)
        }, {
            name: 'Layout Task',
            parent: 'layout-group',
            start: today.getTime() + (5 * day),
            end: today.getTime() + (7 * day)
        }, {
            name: 'Layout Task',
            parent: 'layout-group',
            start: today.getTime() + (7 * day),
            end: today.getTime() + (10 * day)
        }, {
            name: 'Graphics',
            parent: 'design',
            start: today.getTime() + (10 * day),
            end: today.getTime() + (20 * day)
        }]
    }]
})

关键说明

  • 新增的layout-group作为顶级折叠节点,所有Layout相关任务都挂载在它下面,折叠时会统一隐藏/显示所有关联项。
  • 两个Layout任务使用唯一ID,且name相同,通过yAxis.uniqueNames: true自动显示在同一行。
  • 若需子任务仅关联某个特定Layout时间块,只需将子任务的parent设为对应时间任务的ID(如layout-1)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 04:35:55