跳转至

15 · 甘特图

GanttChart 用于展示带时间区间的任务排程,支持任务依赖、进度、基线计划、里程碑、分组图例、层级任务和时间窗口导航。

基础任务

start := time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC)
day := func(offset int) time.Time { return start.AddDate(0, 0, offset) }

tasks := []ui.GanttTask{
    ui.NewGanttTask("design", "设计", day(0), day(5)).
        Group("产品").Progress(.8),
    ui.NewGanttTask("build", "开发", day(4), day(12)).
        Group("工程").DependsOn("design"),
    ui.NewGanttMilestone("launch", "发布", day(12)).
        Group("发布").DependsOn("build"),
}

chart := ui.GanttChart("release-plan", tasks).
    TimeRange(day(-1), day(14)).
    Legend(true).
    TaskLabels(true).
    TaskAxis("任务").
    TimeAxis("2025 年 1 月")

NewGanttTask 的结束时间必须晚于开始时间;零时长节点使用 NewGanttMilestoneDependsOn 使用任务 key,组件会拒绝空 key、未知任务、自依赖和依赖环。

基线与进度

ui.NewGanttTask("build", "开发", day(4), day(12)).
    Baseline(day(3), day(10)).
    Progress(.6)

基线显示在当前任务条下方,进度显示为当前任务条的实色部分。颜色可通过 GroupColor 指定,默认颜色来自主题。

层级任务

ui.NewGanttTask("platform", "平台", day(0), day(20)),
ui.NewGanttTask("api", "公共 API", day(2), day(10)).Parent("platform"),
ui.NewGanttTask("ui", "工作台", day(6), day(16)).Parent("platform"),

父任务会显示展开/折叠控件。没有回调时折叠状态由组件保留;需要受控状态时使用:

chart.OnTaskToggle(func(key string, collapsed bool) {
    // 更新 Model,再用 Collapsed(collapsed) 重建对应任务
})

初始状态可以由 NewGanttTask(...).Collapsed(true) 设置。父任务引用必须存在,且不能形成父子循环。

时间窗口

chart.TimeWindow(day(2), day(10)).OnTimeWindowChange(func(start, end time.Time) {
    // 保存或同步当前窗口
    _ = ui.GanttTimeWindow{Start: start, End: end}
})

启用回调后,图表支持滚轮缩放、拖拽平移和双击恢复完整范围。TimeWindow 只作为初始/受控窗口;组件不会在每次重绘时覆盖用户的手势结果。

拖拽编辑

任务条中部可拖拽移动,左右边缘可调整开始或结束时间。编辑必须显式启用,并通过回调把变更写回 Model:

chart.Editable(true).OnTaskChange(func(change ui.GanttTaskChange) {
    // 用 change.Key 定位任务,并保存 change.Start / change.End
    // change.PreviousStart / change.PreviousEnd 可用于审计或撤销
})

组件只在释放鼠标时提交一次 OnTaskChange,拖动过程显示本地预览。里程碑不支持区间拖拽。

主题与布局

甘特图的行高、条高、圆角、层级缩进、折叠控件尺寸、依赖线和图例间距都在 Theme.Components.GanttChart 中。应用应通过主题覆盖这些 token,而不是在业务代码中绘制覆盖层。

完整示例:examples/gantt_charts