Skip to content

依赖关系

GanttFlow 支持任务之间的多种依赖关系,确保任务按正确的顺序执行。

定义依赖

tsx
const dependencies = [
  { fromId: "1", toId: "2", type: "finish_to_start" },
  { fromId: "2", toId: "3", type: "finish_to_start" },
  { fromId: "2", toId: "4", type: "finish_to_start" },
]

<EnhancedGanttChart
  tasks={tasks}
  dependencies={dependencies}
/>

依赖类型

类型常量说明图示
finish_to_startFSA 结束后,B 开始A ████→ ████ B
start_to_startSSA 开始后,B 开始A ████ ⟷ B
finish_to_finishFFA 结束后,B 结束A ████ ←▸ ████ B
start_to_finishSFA 开始后,B 结束A ████ ⟵ B

类型详解

finish_to_start (FS) - 最常用

前置任务完成后,后续任务才能开始:

任务 A: ████████████
                ↓ (A 完成后 B 开始)
任务 B:              ████████████
tsx
{ fromId: "1", toId: "2", type: "finish_to_start" }
// 任务 1 完成后,任务 2 开始

start_to_start (SS)

前置任务开始后,后续任务也开始:

任务 A: ████████████
任务 B: ████████████ (同时开始)
tsx
{ fromId: "1", toId: "2", type: "start_to_start" }
// 任务 1 开始后,任务 2 也开始

finish_to_finish (FF)

前置任务完成后,后续任务也结束:

任务 A: ████████████
                      ↓ (同时结束)
任务 B:        ████████████
tsx
{ fromId: "1", toId: "2", type: "finish_to_finish" }
// 任务 1 完成后,任务 2 也结束

start_to_finish (SF)

前置任务开始后,后续任务结束:

任务 A: ████████████

任务 B: ████████████  (A 开始后 B 结束)
tsx
{ fromId: "1", toId: "2", type: "start_to_finish" }
// 任务 1 开始后,任务 2 结束

关键路径

关键路径(Critical Path)是项目中最长的依赖链,决定了项目的最短完成时间。关键路径上的任务延迟会直接影响整个项目工期。

启用关键路径

tsx
<EnhancedGanttChart
  tasks={tasks}
  dependencies={dependencies}
  enableCriticalPath={true}     // 启用关键路径
  criticalPathColor="#ef4444"   // 关键路径颜色(红色)
/>

关键路径特点

  • 使用醒目的颜色高亮显示
  • 通常是项目中最长的任务链
  • 任务条会有特殊标识(如边框)

查看关键路径任务

tsx
const handleTaskClick = (task) => {
  const isCritical = ganttRef.current?.isOnCriticalPath(task.id)
  console.log(`${task.name} 是否在关键路径上:`, isCritical)
}

<EnhancedGanttChart
  tasks={tasks}
  dependencies={dependencies}
  enableCriticalPath={true}
  onTaskClick={handleTaskClick}
/>

循环依赖检测

GanttFlow 会自动检测并阻止循环依赖:

tsx
// 这会触发错误
const dependencies = [
  { fromId: "1", toId: "2", type: "finish_to_start" },
  { fromId: "2", toId: "3", type: "finish_to_start" },
  { fromId: "3", toId: "1", type: "finish_to_start" }, // 循环!
]

错误提示:

Error: 检测到循环依赖: 任务1 → 任务2 → 任务3 → 任务1

预防循环依赖

tsx
// 添加依赖前验证
const addDependency = (fromId, toId) => {
  // 创建临时依赖列表
  const tempDeps = [...dependencies, { fromId, toId, type: "finish_to_start" }]
  
  // 检测是否有循环
  if (hasCycle(tempDeps)) {
    alert("无法添加:会导致循环依赖")
    return
  }
  
  setDependencies(tempDeps)
}

// 使用
addDependency("2", "1") // 会提示循环依赖

依赖箭头样式

可以自定义依赖箭头的样式:

tsx
<EnhancedGanttChart
  tasks={tasks}
  dependencies={dependencies}
  dependencyArrowColor="#6b7280"    // 箭头颜色
  dependencyArrowWidth={2}           // 箭头线宽
  dependencyArrowStyle="straight"   // straight | curved
/>

箭头样式

样式说明适用场景
straight直线箭头依赖关系简单
curved曲线箭头避免交叉,更美观

禁用依赖功能

如不需要依赖关系功能,可以禁用以提升性能:

tsx
<EnhancedGanttChart
  tasks={tasks}
  enableDependencies={false}
/>

动态更新依赖

可以在运行时动态添加或删除依赖:

tsx
const [dependencies, setDependencies] = useState(initialDeps)

// 添加依赖
const addDependency = (fromId, toId) => {
  setDependencies([
    ...dependencies,
    { fromId, toId, type: "finish_to_start" }
  ])
}

// 删除依赖
const removeDependency = (fromId, toId) => {
  setDependencies(
    dependencies.filter(
      d => !(d.fromId === fromId && d.toId === toId)
    )
  )
}

// 更新依赖类型
const updateDependencyType = (fromId, toId, newType) => {
  setDependencies(
    dependencies.map(d =>
      d.fromId === fromId && d.toId === toId
        ? { ...d, type: newType }
        : d
    )
  )
}

依赖关系拖拽

支持通过拖拽创建依赖关系:

tsx
<EnhancedGanttChart
  tasks={tasks}
  dependencies={dependencies}
  enableDependencyDrag={true}  // 启用拖拽创建依赖
  onDependencyCreate={(fromId, toId) => {
    console.log(`创建依赖: ${fromId} → ${toId}`)
  }}
/>

拖拽创建依赖的交互

  1. 鼠标悬停在任务右边缘,显示连接点
  2. 拖动连接点到目标任务
  3. 释放鼠标完成创建
  4. 自动推断依赖类型(通常为 FS)

依赖事件

tsx
<EnhancedGanttChart
  tasks={tasks}
  dependencies={dependencies}
  onDependencyAdd={(dependency) => {
    console.log("添加依赖:", dependency)
  }}
  onDependencyDelete={(dependency) => {
    console.log("删除依赖:", dependency)
  }}
  onDependencyError={(error) => {
    console.error("依赖错误:", error.message)
    alert(error.message)
  }}
/>

完整示例

tsx
import React, { useState } from "react"
import { EnhancedGanttChart } from "@agions/gantt-flow"
import "@agions/gantt-flow/style"
import type { Task, Dependency } from "@agions/gantt-flow"

const tasks: Task[] = [
  { id: "1", name: "需求分析", start: "2024-01-01", end: "2024-01-05" },
  { id: "2", name: "系统设计", start: "2024-01-06", end: "2024-01-10" },
  { id: "3", name: "详细设计", start: "2024-01-08", end: "2024-01-12" },
  { id: "4", name: "后端开发", start: "2024-01-13", end: "2024-01-22" },
  { id: "5", name: "前端开发", start: "2024-01-13", end: "2024-01-22" },
  { id: "6", name: "集成测试", start: "2024-01-23", end: "2024-01-28" },
  { id: "7", name: "上线部署", start: "2024-01-29", end: "2024-01-30" },
]

const dependencies: Dependency[] = [
  { fromId: "1", toId: "2", type: "finish_to_start" },
  { fromId: "2", toId: "3", type: "start_to_start" },  // 设计阶段开始后,详细设计开始
  { fromId: "3", toId: "4", type: "finish_to_start" },
  { fromId: "3", toId: "5", type: "finish_to_start" },
  { fromId: "4", toId: "6", type: "finish_to_start" },
  { fromId: "5", toId: "6", type: "finish_to_start" },
  { fromId: "6", toId: "7", type: "finish_to_start" },
]

function ProjectGantt() {
  return (
    <div style={{ height: "600px" }}>
      <EnhancedGanttChart
        tasks={tasks}
        dependencies={dependencies}
        enableCriticalPath={true}
        criticalPathColor="#ef4444"
      />
    </div>
  )
}

export default ProjectGantt

下一步

基于 MIT 许可证发布