依赖关系
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_start | FS | A 结束后,B 开始 | A ████→ ████ B |
start_to_start | SS | A 开始后,B 开始 | A ████ ⟷ B |
finish_to_finish | FF | A 结束后,B 结束 | A ████ ←▸ ████ B |
start_to_finish | SF | A 开始后,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}`)
}}
/>拖拽创建依赖的交互
- 鼠标悬停在任务右边缘,显示连接点
- 拖动连接点到目标任务
- 释放鼠标完成创建
- 自动推断依赖类型(通常为 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