@lee576/vue3-gantt 1.0.8 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en-US.md +1056 -52
- package/README.md +2612 -94
- package/dist/assets/dataProcessor.worker-2qThJYPh.js +2 -0
- package/dist/assets/dataProcessor.worker-2qThJYPh.js.map +1 -0
- package/dist/vue3-gantt.css +1 -1
- package/dist/vue3-gantt.es.js +4103 -3935
- package/dist/vue3-gantt.es.js.map +1 -1
- package/dist/vue3-gantt.umd.js +94 -94
- package/dist/vue3-gantt.umd.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
# Vue3 Gantt 甘特图组件
|
|
2
2
|
|
|
3
|
-
**Languages / 语言选择:**
|
|
3
|
+
**Languages / 语言选择:**
|
|
4
|
+
[<span style="color: #0078d4; font-weight: bold;">简体中文</span>](#chinese-documentation) |
|
|
5
|
+
[<span style="color: #0078d4; font-weight: bold;">English</span>](#english-documentation) |
|
|
6
|
+
[View Separate Files](.)
|
|
4
7
|
|
|
5
|
-
> 💡 **提示**: GitHub 上也可查看独立语言版本文件:[README.md](README.md) (默认中文) | [README.en-US.md](README.en-US.md) (English)
|
|
8
|
+
> 💡 **提示**: 点击上方语言链接可直接跳转到对应文档 | GitHub 上也可查看独立语言版本文件:[README.md](README.md) (默认中文) | [README.en-US.md](README.en-US.md) (English)
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
html {
|
|
12
|
+
scroll-behavior: smooth;
|
|
13
|
+
}
|
|
14
|
+
details > summary {
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
list-style: none;
|
|
17
|
+
}
|
|
18
|
+
details > summary::-webkit-details-marker {
|
|
19
|
+
display: none;
|
|
20
|
+
}
|
|
21
|
+
details[open] > summary {
|
|
22
|
+
border-bottom: 1px solid #e0e0e0;
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
6
25
|
|
|
7
26
|
---
|
|
8
27
|
|
|
9
28
|
<div id="chinese-documentation"></div>
|
|
10
29
|
|
|
11
|
-
<details
|
|
30
|
+
<details>
|
|
12
31
|
<summary><h2>🇨🇳 简体中文文档</h2></summary>
|
|
13
32
|
|
|
14
33
|
一个功能丰富、高度可定制的 Vue 3 甘特图组件,支持任务管理、依赖关系、多种视图模式和主题切换。
|
|
@@ -44,11 +63,12 @@
|
|
|
44
63
|
## ✨ 核心特性
|
|
45
64
|
|
|
46
65
|
### 📅 多视图模式
|
|
47
|
-
|
|
66
|
+
支持五种时间粒度,满足不同场景需求:
|
|
67
|
+
- **季度视图** - 超长期项目规划,按月显示
|
|
48
68
|
- **月视图** - 长期项目规划,按天显示
|
|
49
|
-
- **周视图** - 中期项目跟踪,按周显示
|
|
50
|
-
- **日视图** -
|
|
51
|
-
- **时视图** -
|
|
69
|
+
- **周视图** - 中期项目跟踪,按周显示
|
|
70
|
+
- **日视图** - 短期任务管理,支持全天/半天细分模式
|
|
71
|
+
- **时视图** - 精细任务调度,支持小时/30分钟/15分钟细分模式
|
|
52
72
|
|
|
53
73
|
### 🔗 任务依赖管理
|
|
54
74
|
- **完成-开始 (FS)** - 前置任务完成后,后续任务才能开始
|
|
@@ -62,7 +82,7 @@
|
|
|
62
82
|
- 自动识别(开始时间=结束时间)或手动标记
|
|
63
83
|
|
|
64
84
|
### 🎨 主题系统
|
|
65
|
-
- 内置
|
|
85
|
+
- 内置 7 种精美主题(Metro/Dark/Modern/Classic/Colorful/Apple/Liquid Glass)
|
|
66
86
|
- 支持深色模式,护眼舒适
|
|
67
87
|
- 完整的 CSS 变量支持,轻松自定义主题
|
|
68
88
|
- 主题设置自动保存到浏览器
|
|
@@ -87,6 +107,37 @@
|
|
|
87
107
|
- 计算结果缓存,提升响应速度
|
|
88
108
|
- 按需渲染连线,优化绘制性能
|
|
89
109
|
|
|
110
|
+
### 📝 自定义字段
|
|
111
|
+
- **多种字段类型** - 支持文本、数字、日期、下拉选择等字段类型
|
|
112
|
+
- **灵活配置** - 可为任务添加任意数量的自定义字段
|
|
113
|
+
- **表单验证** - 内置字段验证规则,确保数据有效性
|
|
114
|
+
- **本地存储** - 字段配置自动保存到浏览器,刷新不丢失
|
|
115
|
+
- **动态管理** - 支持运行时添加、编辑、删除自定义字段
|
|
116
|
+
|
|
117
|
+
### 💬 消息提示
|
|
118
|
+
- **三种提示类型** - 成功、错误、警告,满足不同场景需求
|
|
119
|
+
- **自动消失** - 提示信息自动消失,无需手动关闭
|
|
120
|
+
- **优雅动画** - 流畅的进入和退出动画效果
|
|
121
|
+
- **多语言支持** - 提示文本随语言设置自动切换
|
|
122
|
+
|
|
123
|
+
### 🗑️ 删除确认
|
|
124
|
+
- **安全删除** - 删除任务前弹出确认对话框,防止误操作
|
|
125
|
+
- **级联删除** - 删除父任务时自动提示将同时删除所有子任务
|
|
126
|
+
- **友好提示** - 清晰的警告信息,让用户了解删除影响范围
|
|
127
|
+
|
|
128
|
+
### 🎛️ 配置面板
|
|
129
|
+
- **连线样式配置** - 自定义任务连线的路径类型、颜色、宽度、虚线样式、箭头设置
|
|
130
|
+
- **父子关系样式** - 配置父子任务的连接线样式
|
|
131
|
+
- **列显示设置** - 灵活控制任务列表列的显示/隐藏
|
|
132
|
+
- **一键重置** - 快速恢复默认配置
|
|
133
|
+
|
|
134
|
+
### 🌲 树形任务结构
|
|
135
|
+
- **层级展示** - 清晰的树形结构显示任务父子关系
|
|
136
|
+
- **折叠展开** - 支持折叠/展开子任务,简化视图
|
|
137
|
+
- **连接线** - 可视化连接线展示层级关系
|
|
138
|
+
- **快速操作** - 行内按钮快速添加/删除子任务
|
|
139
|
+
- **悬停高亮** - 鼠标悬停时高亮显示当前任务行
|
|
140
|
+
|
|
90
141
|
## 🚀 安装使用
|
|
91
142
|
|
|
92
143
|
### 方式一:通过 npm 安装(推荐)
|
|
@@ -449,19 +500,36 @@ dependencies: [
|
|
|
449
500
|
|
|
450
501
|
| 模式 | 时间单位 | 表头示例 | 适用场景 |
|
|
451
502
|
|------|----------|----------|----------|
|
|
452
|
-
|
|
|
503
|
+
| � **季度视图** | 月 | `2024-Q1 2024-Q2 2024-Q3 ...` | 超长期项目规划 |
|
|
504
|
+
| ��️ **月视图** | 天 | `01 02 03 04 05 ...` | 长期项目规划 |
|
|
453
505
|
| 📅 **日视图** | 天 | `周一 周二 周三 ...` | 短期任务管理 |
|
|
454
506
|
| 📊 **周视图** | 周 | `W50 W51 W52 ...` | 中期项目跟踪 |
|
|
455
507
|
| ⏰ **时视图** | 小时 | `08 09 10 11 12 ...` | 精细任务调度 |
|
|
456
508
|
|
|
457
|
-
|
|
509
|
+
组件支持五种时间粒度视图:
|
|
458
510
|
|
|
459
|
-
| 模式 | 说明 | 适用场景 |
|
|
460
|
-
|
|
461
|
-
|
|
|
462
|
-
|
|
|
463
|
-
|
|
|
464
|
-
|
|
|
511
|
+
| 模式 | 说明 | 细分模式 | 适用场景 |
|
|
512
|
+
|------|------|----------|----------|
|
|
513
|
+
| 季度 | 按月显示,以季度为单位 | - | 超长期项目规划 |
|
|
514
|
+
| 月 | 按天显示,以月份为单位 | - | 长期项目规划 |
|
|
515
|
+
| 日 | 按天显示,精确到天 | 全天 / 半天 | 短期任务管理 |
|
|
516
|
+
| 周 | 按周显示 | - | 中期项目跟踪 |
|
|
517
|
+
| 时 | 按小时显示 | 小时 / 30分钟 / 15分钟 | 精细任务调度 |
|
|
518
|
+
|
|
519
|
+
### 视图模式切换
|
|
520
|
+
|
|
521
|
+
组件顶部提供视图模式切换按钮,点击即可在不同视图模式之间切换。
|
|
522
|
+
|
|
523
|
+
### 细分模式说明
|
|
524
|
+
|
|
525
|
+
**日视图细分模式:**
|
|
526
|
+
- **全天** - 每天显示为一个完整的时间段
|
|
527
|
+
- **半天** - 每天分为上午和下午两个时间段
|
|
528
|
+
|
|
529
|
+
**时视图细分模式:**
|
|
530
|
+
- **小时** - 每小时显示为一个时间段
|
|
531
|
+
- **30分钟** - 每小时分为两个30分钟时间段
|
|
532
|
+
- **15分钟** - 每小时分为四个15分钟时间段
|
|
465
533
|
|
|
466
534
|
## 主题系统
|
|
467
535
|
|
|
@@ -472,6 +540,8 @@ dependencies: [
|
|
|
472
540
|
| ✨ **现代简约** | `#6366f1` | 简洁现代设计,清爽舒适 |
|
|
473
541
|
| 💼 **经典商务** | `#2563eb` | 传统商务风格,稳重大方 |
|
|
474
542
|
| 🎨 **彩色活力** | `#f59e0b` | 活泼彩色主题,充满活力 |
|
|
543
|
+
| 🍎 **Apple 风格** | `#007aff` | 简约优雅的 macOS 风格,流畅自然 |
|
|
544
|
+
| 💧 **Liquid Glass** | `#007aff` | iOS 26 液态玻璃效果,半透明流动质感 |
|
|
475
545
|
|
|
476
546
|
### 内置主题
|
|
477
547
|
|
|
@@ -482,6 +552,8 @@ dependencies: [
|
|
|
482
552
|
| modern | 现代简约 | 简洁现代设计 |
|
|
483
553
|
| classic | 经典商务 | 传统商务风格 |
|
|
484
554
|
| colorful | 彩色活力 | 活泼彩色主题 |
|
|
555
|
+
| apple | Apple 风格 | 简约优雅的 macOS 风格 |
|
|
556
|
+
| liquidGlass | Liquid Glass | iOS 26 液态玻璃效果 |
|
|
485
557
|
|
|
486
558
|
### 切换主题
|
|
487
559
|
|
|
@@ -505,9 +577,659 @@ dependencies: [
|
|
|
505
577
|
}
|
|
506
578
|
```
|
|
507
579
|
|
|
508
|
-
##
|
|
580
|
+
## 自定义字段
|
|
581
|
+
|
|
582
|
+
组件支持强大的自定义字段功能,允许为任务添加任意数量的自定义字段,满足不同项目的个性化需求。
|
|
583
|
+
|
|
584
|
+
### 功能特性
|
|
585
|
+
|
|
586
|
+
- **多种字段类型** - 文本、数字、日期、下拉选择
|
|
587
|
+
- **动态管理** - 运行时添加、编辑、删除字段
|
|
588
|
+
- **表单验证** - 内置验证规则,确保数据有效性
|
|
589
|
+
- **本地存储** - 字段配置自动保存到浏览器
|
|
590
|
+
- **任务绑定** - 自定义字段值与任务数据关联
|
|
591
|
+
|
|
592
|
+
### 字段类型
|
|
593
|
+
|
|
594
|
+
| 类型 | 说明 | 示例值 |
|
|
595
|
+
|------|------|--------|
|
|
596
|
+
| 文本 | 单行文本输入 | "项目编号:PRJ-001" |
|
|
597
|
+
| 数字 | 数值输入,支持小数 | 100.5 |
|
|
598
|
+
| 日期 | 日期选择器 | "2024-12-01" |
|
|
599
|
+
| 下拉选择 | 预定义选项列表 | "高优先级" |
|
|
600
|
+
|
|
601
|
+
### 使用方法
|
|
602
|
+
|
|
603
|
+
#### 1. 打开自定义字段管理
|
|
604
|
+
|
|
605
|
+
在甘特图工具栏中点击"自定义字段"按钮,打开字段管理对话框。
|
|
606
|
+
|
|
607
|
+
#### 2. 添加自定义字段
|
|
608
|
+
|
|
609
|
+
```typescript
|
|
610
|
+
// 示例:添加一个"负责人"字段
|
|
611
|
+
const customField = {
|
|
612
|
+
id: 'field-1',
|
|
613
|
+
name: '负责人',
|
|
614
|
+
type: 'text', // text | number | date | select
|
|
615
|
+
required: false, // 是否必填
|
|
616
|
+
options: [] // 下拉选择时提供选项
|
|
617
|
+
};
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
#### 3. 在任务中使用自定义字段
|
|
621
|
+
|
|
622
|
+
自定义字段的值存储在任务的 `customFieldValues` 字段中:
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
{
|
|
626
|
+
id: '1',
|
|
627
|
+
taskNo: '项目规划',
|
|
628
|
+
start_date: '2024-12-01',
|
|
629
|
+
end_date: '2024-12-06',
|
|
630
|
+
job_progress: '0.85',
|
|
631
|
+
customFieldValues: {
|
|
632
|
+
'field-1': '张三', // 负责人
|
|
633
|
+
'field-2': '100', // 预算
|
|
634
|
+
'field-3': '2024-11-30', // 审批日期
|
|
635
|
+
'field-4': '高优先级' // 优先级
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
#### 4. 下拉选择字段配置
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
const priorityField = {
|
|
644
|
+
id: 'field-priority',
|
|
645
|
+
name: '优先级',
|
|
646
|
+
type: 'select',
|
|
647
|
+
required: true,
|
|
648
|
+
options: [
|
|
649
|
+
{ label: '紧急', value: 'urgent' },
|
|
650
|
+
{ label: '重要', value: 'important' },
|
|
651
|
+
{ label: '一般', value: 'normal' }
|
|
652
|
+
]
|
|
653
|
+
};
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
### 字段验证
|
|
657
|
+
|
|
658
|
+
组件内置了基本的字段验证规则:
|
|
659
|
+
|
|
660
|
+
- **必填字段** - 如果字段标记为 `required: true`,则必须提供值
|
|
661
|
+
- **数字验证** - 数字字段只接受有效的数值
|
|
662
|
+
- **日期验证** - 日期字段只接受有效的日期格式
|
|
663
|
+
- **选项验证** - 下拉选择字段只接受预定义的选项值
|
|
664
|
+
|
|
665
|
+
### API 集成
|
|
666
|
+
|
|
667
|
+
#### 后端存储格式
|
|
668
|
+
|
|
669
|
+
自定义字段值需要以特定格式存储到后端:
|
|
670
|
+
|
|
671
|
+
```typescript
|
|
672
|
+
// 推荐格式:JSON 字符串
|
|
673
|
+
customFieldValues: JSON.stringify({
|
|
674
|
+
'field-1': '张三',
|
|
675
|
+
'field-2': '100'
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
// 或数组格式(需要后端支持)
|
|
679
|
+
customFieldValues: [
|
|
680
|
+
{ fieldId: 'field-1', value: '张三' },
|
|
681
|
+
{ fieldId: 'field-2', value: '100' }
|
|
682
|
+
]
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
#### 数据处理示例
|
|
686
|
+
|
|
687
|
+
```typescript
|
|
688
|
+
// 保存任务时
|
|
689
|
+
const saveTask = async (task) => {
|
|
690
|
+
const payload = {
|
|
691
|
+
...task,
|
|
692
|
+
customFieldValues: JSON.stringify(task.customFieldValues)
|
|
693
|
+
};
|
|
694
|
+
await api.saveTask(payload);
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
// 加载任务时
|
|
698
|
+
const loadTask = async (taskId) => {
|
|
699
|
+
const data = await api.getTask(taskId);
|
|
700
|
+
return {
|
|
701
|
+
...data,
|
|
702
|
+
customFieldValues: JSON.parse(data.customFieldValues || '{}')
|
|
703
|
+
};
|
|
704
|
+
};
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### 最佳实践
|
|
708
|
+
|
|
709
|
+
1. **字段命名** - 使用清晰、简洁的字段名称,便于理解
|
|
710
|
+
2. **必填设置** - 合理设置必填字段,避免过度限制
|
|
711
|
+
3. **选项管理** - 下拉选择字段提供完整的选项列表
|
|
712
|
+
4. **数据验证** - 在后端也进行字段验证,确保数据完整性
|
|
713
|
+
5. **性能优化** - 避免添加过多自定义字段,影响性能
|
|
714
|
+
|
|
715
|
+
## 配置面板
|
|
716
|
+
|
|
717
|
+
组件提供了丰富的配置选项,允许用户自定义甘特图的外观和行为。
|
|
718
|
+
|
|
719
|
+
### 甘特图配置面板
|
|
720
|
+
|
|
721
|
+
点击工具栏中的"设置"按钮,打开甘特图配置面板。
|
|
722
|
+
|
|
723
|
+
#### 语言设置
|
|
724
|
+
|
|
725
|
+
- 支持切换 8 种语言(中/英/日/韩/法/德/西/俄)
|
|
726
|
+
- 语言设置自动保存到浏览器
|
|
727
|
+
- 切换后界面立即更新,无需刷新
|
|
728
|
+
|
|
729
|
+
#### 主题设置
|
|
730
|
+
|
|
731
|
+
- 5 种内置主题可选
|
|
732
|
+
- 主题切换即时生效
|
|
733
|
+
- 主题设置自动保存
|
|
734
|
+
|
|
735
|
+
#### 连线样式配置
|
|
736
|
+
|
|
737
|
+
| 配置项 | 说明 | 可选值 |
|
|
738
|
+
|--------|------|--------|
|
|
739
|
+
| 路径类型 | 连线的绘制路径 | 直线 / 贝塞尔曲线 / 阶梯线 |
|
|
740
|
+
| 连线颜色 | 连线的颜色 | 颜色选择器 |
|
|
741
|
+
| 连线宽度 | 连线的粗细 | 1px - 5px |
|
|
742
|
+
| 虚线样式 | 是否使用虚线 | 实线 / 虚线 |
|
|
743
|
+
| 箭头设置 | 是否显示箭头 | 显示 / 隐藏 |
|
|
744
|
+
|
|
745
|
+
#### 父子关系样式
|
|
746
|
+
|
|
747
|
+
| 配置项 | 说明 |
|
|
748
|
+
|--------|------|
|
|
749
|
+
| 连接线颜色 | 父子任务连接线的颜色 |
|
|
750
|
+
| 连接线宽度 | 父子任务连接线的粗细 |
|
|
751
|
+
| 连接线样式 | 实线或虚线 |
|
|
752
|
+
|
|
753
|
+
### 列显示设置面板
|
|
754
|
+
|
|
755
|
+
点击工具栏中的"列设置"按钮,打开列显示设置面板。
|
|
756
|
+
|
|
757
|
+
#### 功能特性
|
|
758
|
+
|
|
759
|
+
- **列显示控制** - 勾选/取消勾选来显示或隐藏列
|
|
760
|
+
- **全部显示** - 一键显示所有列
|
|
761
|
+
- **全部隐藏** - 一键隐藏所有列
|
|
762
|
+
- **重置默认** - 恢复到默认列配置
|
|
763
|
+
- **实时生效** - 设置更改立即反映在界面上
|
|
764
|
+
|
|
765
|
+
#### 默认列配置
|
|
766
|
+
|
|
767
|
+
```typescript
|
|
768
|
+
taskHeaders: [
|
|
769
|
+
{ title: '序号', width: 80, property: 'no', show: true },
|
|
770
|
+
{ title: '任务名称', width: 200, property: 'task', show: true },
|
|
771
|
+
{ title: '优先级', width: 90, property: 'priority', show: true },
|
|
772
|
+
{ title: '开始时间', width: 150, property: 'startdate', show: true },
|
|
773
|
+
{ title: '结束时间', width: 150, property: 'enddate', show: true },
|
|
774
|
+
{ title: '耗时', width: 100, property: 'takestime', show: true },
|
|
775
|
+
{ title: '进度', width: 100, property: 'progress', show: true }
|
|
776
|
+
]
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### 配置持久化
|
|
780
|
+
|
|
781
|
+
所有配置(语言、主题、连线样式、列显示等)都会自动保存到浏览器的 localStorage 中,刷新页面后配置不会丢失。
|
|
782
|
+
|
|
783
|
+
### 编程方式配置
|
|
784
|
+
|
|
785
|
+
除了通过界面配置,也可以通过代码直接设置配置:
|
|
786
|
+
|
|
787
|
+
```typescript
|
|
788
|
+
// 设置主题
|
|
789
|
+
import { setTheme } from './components/gantt/theme';
|
|
790
|
+
setTheme('dark');
|
|
791
|
+
|
|
792
|
+
// 设置语言
|
|
793
|
+
import { setLocale } from './components/gantt/i18n';
|
|
794
|
+
setLocale('en-US');
|
|
795
|
+
|
|
796
|
+
// 修改列配置
|
|
797
|
+
dataConfig.value.taskHeaders = [
|
|
798
|
+
{ title: '序号', width: 80, property: 'no', show: true },
|
|
799
|
+
{ title: '任务名称', width: 250, property: 'task', show: true },
|
|
800
|
+
// ... 其他列
|
|
801
|
+
];
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
## 任务对话框
|
|
805
|
+
|
|
806
|
+
组件提供了完整的任务创建和编辑对话框,支持基础字段和自定义字段的编辑。
|
|
807
|
+
|
|
808
|
+
### 对话框功能
|
|
809
|
+
|
|
810
|
+
#### 基础字段
|
|
811
|
+
|
|
812
|
+
| 字段 | 说明 | 必填 |
|
|
813
|
+
|------|------|------|
|
|
814
|
+
| 任务名称 | 任务的名称 | ✅ |
|
|
815
|
+
| 优先级 | 任务的优先级(紧急/重要/一般) | ✅ |
|
|
816
|
+
| 开始时间 | 任务的开始日期和时间 | ✅ |
|
|
817
|
+
| 结束时间 | 任务的结束日期和时间 | ✅ |
|
|
818
|
+
| 进度 | 任务的完成进度(0-100%) | ✅ |
|
|
819
|
+
|
|
820
|
+
#### 自定义字段
|
|
821
|
+
|
|
822
|
+
根据配置的自定义字段,对话框会动态显示相应的输入控件。
|
|
823
|
+
|
|
824
|
+
### 打开对话框
|
|
825
|
+
|
|
826
|
+
#### 创建根任务
|
|
827
|
+
|
|
828
|
+
```typescript
|
|
829
|
+
// 通过工具栏按钮点击
|
|
830
|
+
eventConfig.value.addRootTask?.(newTask);
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
#### 创建子任务
|
|
834
|
+
|
|
835
|
+
```typescript
|
|
836
|
+
// 在任务行点击"添加子任务"按钮
|
|
837
|
+
eventConfig.value.addSubTask?.(parentTask);
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
#### 编辑任务
|
|
841
|
+
|
|
842
|
+
```typescript
|
|
843
|
+
// 双击任务或点击编辑按钮
|
|
844
|
+
eventConfig.value.editTask?.(task);
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
### 表单验证
|
|
848
|
+
|
|
849
|
+
对话框内置了表单验证功能:
|
|
850
|
+
|
|
851
|
+
- **必填字段检查** - 确保所有必填字段都已填写
|
|
852
|
+
- **日期逻辑验证** - 结束时间不能早于开始时间
|
|
853
|
+
- **进度范围验证** - 进度值必须在 0-100 之间
|
|
854
|
+
- **自定义字段验证** - 根据字段配置进行验证
|
|
855
|
+
|
|
856
|
+
### 对话框事件
|
|
857
|
+
|
|
858
|
+
```typescript
|
|
859
|
+
const eventConfig = ref<EventConfig>({
|
|
860
|
+
// 添加根任务
|
|
861
|
+
addRootTask: (task) => {
|
|
862
|
+
console.log('添加根任务', task);
|
|
863
|
+
// 保存到后端
|
|
864
|
+
await api.createTask(task);
|
|
865
|
+
},
|
|
866
|
+
|
|
867
|
+
// 添加子任务
|
|
868
|
+
addSubTask: (parentTask) => {
|
|
869
|
+
console.log('添加子任务,父任务:', parentTask);
|
|
870
|
+
// 创建子任务
|
|
871
|
+
const subTask = {
|
|
872
|
+
pid: parentTask.id,
|
|
873
|
+
// ... 其他字段
|
|
874
|
+
};
|
|
875
|
+
await api.createTask(subTask);
|
|
876
|
+
},
|
|
877
|
+
|
|
878
|
+
// 编辑任务
|
|
879
|
+
editTask: (task) => {
|
|
880
|
+
console.log('编辑任务', task);
|
|
881
|
+
// 更新到后端
|
|
882
|
+
await api.updateTask(task);
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
```
|
|
509
886
|
|
|
510
|
-
|
|
887
|
+
### 对话框样式
|
|
888
|
+
|
|
889
|
+
对话框采用现代化的设计风格:
|
|
890
|
+
|
|
891
|
+
- **模态窗口** - 阻止背景操作,确保用户专注
|
|
892
|
+
- **响应式布局** - 自适应不同屏幕尺寸
|
|
893
|
+
- **清晰的标签** - 每个字段都有明确的标签
|
|
894
|
+
- **必填标识** - 必填字段有红色星号标记
|
|
895
|
+
- **错误提示** - 验证失败时显示错误信息
|
|
896
|
+
|
|
897
|
+
## 消息提示
|
|
898
|
+
|
|
899
|
+
组件内置了优雅的消息提示系统,用于向用户反馈操作结果。
|
|
900
|
+
|
|
901
|
+
### 提示类型
|
|
902
|
+
|
|
903
|
+
| 类型 | 说明 | 图标 | 颜色 |
|
|
904
|
+
|------|------|------|------|
|
|
905
|
+
| 成功 | 操作成功完成 | ✅ | 绿色 |
|
|
906
|
+
| 错误 | 操作失败或出错 | ❌ | 红色 |
|
|
907
|
+
| 警告 | 需要注意的问题 | ⚠️ | 黄色 |
|
|
908
|
+
|
|
909
|
+
### 使用方法
|
|
910
|
+
|
|
911
|
+
#### 1. 通过组件内部触发
|
|
912
|
+
|
|
913
|
+
组件内部会在以下情况自动显示消息提示:
|
|
914
|
+
|
|
915
|
+
- 任务创建成功/失败
|
|
916
|
+
- 任务更新成功/失败
|
|
917
|
+
- 任务删除成功/失败
|
|
918
|
+
- 自定义字段保存成功/失败
|
|
919
|
+
- 配置更新成功
|
|
920
|
+
|
|
921
|
+
#### 2. 编程方式调用
|
|
922
|
+
|
|
923
|
+
```typescript
|
|
924
|
+
import { showToast } from './components/MessageToast';
|
|
925
|
+
|
|
926
|
+
// 显示成功消息
|
|
927
|
+
showToast('success', '任务创建成功!');
|
|
928
|
+
|
|
929
|
+
// 显示错误消息
|
|
930
|
+
showToast('error', '操作失败,请重试');
|
|
931
|
+
|
|
932
|
+
// 显示警告消息
|
|
933
|
+
showToast('warning', '请注意:此操作不可撤销');
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
### 提示特性
|
|
937
|
+
|
|
938
|
+
- **自动消失** - 提示信息在 3 秒后自动消失
|
|
939
|
+
- **手动关闭** - 点击关闭按钮可立即关闭
|
|
940
|
+
- **优雅动画** - 流畅的淡入淡出动画
|
|
941
|
+
- **多语言支持** - 提示文本随语言设置自动切换
|
|
942
|
+
- **位置固定** - 固定在页面右上角,不遮挡操作区域
|
|
943
|
+
|
|
944
|
+
### 消息示例
|
|
945
|
+
|
|
946
|
+
```typescript
|
|
947
|
+
// 成功提示
|
|
948
|
+
showToast('success', '任务已成功保存');
|
|
949
|
+
|
|
950
|
+
// 错误提示
|
|
951
|
+
showToast('error', '保存失败:网络连接错误');
|
|
952
|
+
|
|
953
|
+
// 警告提示
|
|
954
|
+
showToast('warning', '删除任务将同时删除所有子任务');
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
## 删除确认对话框
|
|
958
|
+
|
|
959
|
+
为了防止误操作,组件在删除任务时会弹出确认对话框。
|
|
960
|
+
|
|
961
|
+
### 对话框功能
|
|
962
|
+
|
|
963
|
+
- **删除警告** - 清晰的警告信息
|
|
964
|
+
- **级联删除提示** - 如果删除父任务,会提示将同时删除所有子任务
|
|
965
|
+
- **确认/取消** - 用户可以选择确认或取消删除操作
|
|
966
|
+
|
|
967
|
+
### 删除流程
|
|
968
|
+
|
|
969
|
+
```
|
|
970
|
+
用户点击删除按钮
|
|
971
|
+
↓
|
|
972
|
+
检查是否有子任务
|
|
973
|
+
↓
|
|
974
|
+
显示确认对话框
|
|
975
|
+
↓
|
|
976
|
+
用户确认删除
|
|
977
|
+
↓
|
|
978
|
+
执行删除操作
|
|
979
|
+
↓
|
|
980
|
+
显示删除结果提示
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
### 对话框内容
|
|
984
|
+
|
|
985
|
+
#### 删除普通任务
|
|
986
|
+
|
|
987
|
+
```
|
|
988
|
+
⚠️ 确认删除
|
|
989
|
+
|
|
990
|
+
您确定要删除此任务吗?
|
|
991
|
+
|
|
992
|
+
此操作不可撤销。
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
#### 删除父任务(包含子任务)
|
|
996
|
+
|
|
997
|
+
```
|
|
998
|
+
⚠️ 确认删除
|
|
999
|
+
|
|
1000
|
+
您确定要删除此任务吗?
|
|
1001
|
+
|
|
1002
|
+
注意:删除此任务将同时删除其所有子任务(共 3 个)。
|
|
1003
|
+
|
|
1004
|
+
此操作不可撤销。
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
### 事件处理
|
|
1008
|
+
|
|
1009
|
+
```typescript
|
|
1010
|
+
const eventConfig = ref<EventConfig>({
|
|
1011
|
+
removeTask: async (task) => {
|
|
1012
|
+
// 检查是否有子任务
|
|
1013
|
+
const hasChildren = dataConfig.value.dataSource.some(
|
|
1014
|
+
t => t.pid === task.id
|
|
1015
|
+
);
|
|
1016
|
+
|
|
1017
|
+
// 显示确认对话框
|
|
1018
|
+
const confirmed = await showDeleteConfirm(task, hasChildren);
|
|
1019
|
+
|
|
1020
|
+
if (confirmed) {
|
|
1021
|
+
// 执行删除
|
|
1022
|
+
await api.deleteTask(task.id);
|
|
1023
|
+
// 更新数据源
|
|
1024
|
+
dataConfig.value.dataSource = dataConfig.value.dataSource.filter(
|
|
1025
|
+
t => t.id !== task.id
|
|
1026
|
+
);
|
|
1027
|
+
// 显示成功提示
|
|
1028
|
+
showToast('success', '任务已删除');
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
### 安全特性
|
|
1035
|
+
|
|
1036
|
+
- **二次确认** - 所有删除操作都需要用户确认
|
|
1037
|
+
- **级联提示** - 明确告知用户删除的影响范围
|
|
1038
|
+
- **不可撤销警告** - 提醒用户操作的不可逆性
|
|
1039
|
+
- **子任务统计** - 显示将要删除的子任务数量
|
|
1040
|
+
|
|
1041
|
+
## 树形任务结构
|
|
1042
|
+
|
|
1043
|
+
组件支持完整的树形任务结构,可以清晰地展示任务的层级关系。
|
|
1044
|
+
|
|
1045
|
+
### 核心特性
|
|
1046
|
+
|
|
1047
|
+
- **层级展示** - 通过缩进和连接线清晰展示父子关系
|
|
1048
|
+
- **折叠展开** - 支持折叠/展开子任务,简化复杂项目视图
|
|
1049
|
+
- **视觉连接** - 树形连接线直观展示任务层级
|
|
1050
|
+
- **快速操作** - 行内按钮快速添加/删除子任务
|
|
1051
|
+
- **悬停高亮** - 鼠标悬停时高亮显示当前任务行
|
|
1052
|
+
|
|
1053
|
+
### 任务层级结构
|
|
1054
|
+
|
|
1055
|
+
```typescript
|
|
1056
|
+
// 根任务(pid = '0')
|
|
1057
|
+
{
|
|
1058
|
+
id: '1',
|
|
1059
|
+
pid: '0', // '0' 表示根任务
|
|
1060
|
+
taskNo: '项目开发',
|
|
1061
|
+
start_date: '2024-12-01',
|
|
1062
|
+
end_date: '2024-12-31'
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// 子任务
|
|
1066
|
+
{
|
|
1067
|
+
id: '1-1',
|
|
1068
|
+
pid: '1', // 父任务ID
|
|
1069
|
+
taskNo: '前端开发',
|
|
1070
|
+
start_date: '2024-12-01',
|
|
1071
|
+
end_date: '2024-12-15'
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// 孙任务
|
|
1075
|
+
{
|
|
1076
|
+
id: '1-1-1',
|
|
1077
|
+
pid: '1-1', // 父任务ID
|
|
1078
|
+
taskNo: 'UI设计',
|
|
1079
|
+
start_date: '2024-12-01',
|
|
1080
|
+
end_date: '2024-12-05'
|
|
1081
|
+
}
|
|
1082
|
+
```
|
|
1083
|
+
|
|
1084
|
+
### 视觉元素
|
|
1085
|
+
|
|
1086
|
+
#### 1. 缩进显示
|
|
1087
|
+
|
|
1088
|
+
子任务会根据层级自动缩进,每层缩进固定距离:
|
|
1089
|
+
|
|
1090
|
+
```
|
|
1091
|
+
├─ 项目开发
|
|
1092
|
+
│ ├─ 前端开发
|
|
1093
|
+
│ │ ├─ UI设计
|
|
1094
|
+
│ │ └─ 功能开发
|
|
1095
|
+
│ └─ 后端开发
|
|
1096
|
+
│ ├─ API设计
|
|
1097
|
+
│ └─ 数据库设计
|
|
1098
|
+
```
|
|
1099
|
+
|
|
1100
|
+
#### 2. 连接线
|
|
1101
|
+
|
|
1102
|
+
树形连接线清晰地展示父子关系:
|
|
1103
|
+
|
|
1104
|
+
- **垂直线** - 连接父任务到子任务
|
|
1105
|
+
- **水平线** - 标记任务的层级位置
|
|
1106
|
+
- **分支线** - 展示任务的分支结构
|
|
1107
|
+
|
|
1108
|
+
#### 3. 折叠/展开按钮
|
|
1109
|
+
|
|
1110
|
+
每个有子任务的任务左侧都有折叠/展开按钮:
|
|
1111
|
+
|
|
1112
|
+
- **展开状态** (▶) - 显示所有子任务
|
|
1113
|
+
- **折叠状态** (▼) - 隐藏所有子任务
|
|
1114
|
+
|
|
1115
|
+
### 交互操作
|
|
1116
|
+
|
|
1117
|
+
#### 添加子任务
|
|
1118
|
+
|
|
1119
|
+
在任务行点击"添加子任务"按钮,会自动:
|
|
1120
|
+
|
|
1121
|
+
1. 创建新的子任务
|
|
1122
|
+
2. 设置正确的父任务ID
|
|
1123
|
+
3. 打开任务编辑对话框
|
|
1124
|
+
4. 保存后自动刷新树形结构
|
|
1125
|
+
|
|
1126
|
+
```typescript
|
|
1127
|
+
const addSubTask = (parentTask) => {
|
|
1128
|
+
const newTask = {
|
|
1129
|
+
id: generateId(),
|
|
1130
|
+
pid: parentTask.id, // 设置父任务ID
|
|
1131
|
+
taskNo: '新子任务',
|
|
1132
|
+
start_date: parentTask.start_date,
|
|
1133
|
+
end_date: parentTask.end_date,
|
|
1134
|
+
job_progress: '0'
|
|
1135
|
+
};
|
|
1136
|
+
eventConfig.value.addSubTask?.(newTask);
|
|
1137
|
+
};
|
|
1138
|
+
```
|
|
1139
|
+
|
|
1140
|
+
#### 删除任务
|
|
1141
|
+
|
|
1142
|
+
删除任务时会:
|
|
1143
|
+
|
|
1144
|
+
1. 检查是否有子任务
|
|
1145
|
+
2. 显示确认对话框(包含级联删除提示)
|
|
1146
|
+
3. 删除任务及其所有子任务
|
|
1147
|
+
4. 自动更新树形结构
|
|
1148
|
+
|
|
1149
|
+
```typescript
|
|
1150
|
+
const deleteTask = (task) => {
|
|
1151
|
+
// 级联删除所有子任务
|
|
1152
|
+
const deleteRecursive = (taskId) => {
|
|
1153
|
+
const children = dataConfig.value.dataSource.filter(
|
|
1154
|
+
t => t.pid === taskId
|
|
1155
|
+
);
|
|
1156
|
+
children.forEach(child => deleteRecursive(child.id));
|
|
1157
|
+
dataConfig.value.dataSource = dataConfig.value.dataSource.filter(
|
|
1158
|
+
t => t.id !== taskId
|
|
1159
|
+
);
|
|
1160
|
+
};
|
|
1161
|
+
deleteRecursive(task.id);
|
|
1162
|
+
};
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
#### 折叠/展开
|
|
1166
|
+
|
|
1167
|
+
点击折叠/展开按钮可以:
|
|
1168
|
+
|
|
1169
|
+
- **展开** - 显示所有子任务和孙任务
|
|
1170
|
+
- **折叠** - 隐藏所有后代任务
|
|
1171
|
+
- **状态记忆** - 折叠状态会保存到 localStorage
|
|
1172
|
+
|
|
1173
|
+
### 父子任务联动
|
|
1174
|
+
|
|
1175
|
+
父任务移动时,子任务会自动跟随移动,保持相对时间关系:
|
|
1176
|
+
|
|
1177
|
+
```typescript
|
|
1178
|
+
// 父任务移动 5 天
|
|
1179
|
+
const moveParentTask = (task, days) => {
|
|
1180
|
+
const oldStart = dayjs(task.start_date);
|
|
1181
|
+
const oldEnd = dayjs(task.end_date);
|
|
1182
|
+
|
|
1183
|
+
// 更新父任务
|
|
1184
|
+
task.start_date = oldStart.add(days, 'day').format('YYYY-MM-DD');
|
|
1185
|
+
task.end_date = oldEnd.add(days, 'day').format('YYYY-MM-DD');
|
|
1186
|
+
|
|
1187
|
+
// 子任务跟随移动
|
|
1188
|
+
const children = getChildren(task.id);
|
|
1189
|
+
children.forEach(child => {
|
|
1190
|
+
const childOldStart = dayjs(child.start_date);
|
|
1191
|
+
const childOldEnd = dayjs(child.end_date);
|
|
1192
|
+
child.start_date = childOldStart.add(days, 'day').format('YYYY-MM-DD');
|
|
1193
|
+
child.end_date = childOldEnd.add(days, 'day').format('YYYY-MM-DD');
|
|
1194
|
+
});
|
|
1195
|
+
};
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
### 样式自定义
|
|
1199
|
+
|
|
1200
|
+
可以通过 CSS 自定义树形结构的样式:
|
|
1201
|
+
|
|
1202
|
+
```css
|
|
1203
|
+
/* 连接线颜色 */
|
|
1204
|
+
.gantt-tree-line {
|
|
1205
|
+
border-color: #d0d0d0;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/* 折叠/展开按钮 */
|
|
1209
|
+
.gantt-collapse-btn {
|
|
1210
|
+
color: #666;
|
|
1211
|
+
cursor: pointer;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
.gantt-collapse-btn:hover {
|
|
1215
|
+
color: #333;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
/* 行悬停效果 */
|
|
1219
|
+
.gantt-row:hover {
|
|
1220
|
+
background-color: #f5f5f5;
|
|
1221
|
+
}
|
|
1222
|
+
```
|
|
1223
|
+
|
|
1224
|
+
### 最佳实践
|
|
1225
|
+
|
|
1226
|
+
1. **合理层级** - 建议层级不超过 5 层,过深的层级会影响可读性
|
|
1227
|
+
2. **任务命名** - 使用清晰的命名规范,便于理解层级关系
|
|
1228
|
+
3. **折叠管理** - 对于大型项目,合理使用折叠功能简化视图
|
|
1229
|
+
4. **批量操作** - 父任务移动时子任务自动跟随,避免逐个调整
|
|
1230
|
+
5. **性能优化** - 深层嵌套时注意性能,考虑使用折叠减少渲染数量
|
|
1231
|
+
|
|
1232
|
+
## 国际化支持
|
|
511
1233
|
|
|
512
1234
|
### 支持的语言
|
|
513
1235
|
|
|
@@ -739,47 +1461,96 @@ interface LinkConfig {
|
|
|
739
1461
|
```
|
|
740
1462
|
src/
|
|
741
1463
|
├── components/
|
|
1464
|
+
│ ├── CustomFieldsDialog.vue # 自定义字段对话框
|
|
1465
|
+
│ ├── DeleteConfirmDialog.vue # 删除确认对话框
|
|
1466
|
+
│ ├── MessageToast.vue # 消息提示组件
|
|
1467
|
+
│ ├── TaskDialog.vue # 任务编辑对话框
|
|
742
1468
|
│ └── gantt/
|
|
743
|
-
│ ├──
|
|
744
|
-
│ ├──
|
|
745
|
-
│ ├──
|
|
746
|
-
│ ├──
|
|
747
|
-
│
|
|
748
|
-
│ ├──
|
|
749
|
-
│ ├──
|
|
750
|
-
│ ├──
|
|
751
|
-
│ ├──
|
|
752
|
-
│ ├──
|
|
753
|
-
│ ├──
|
|
754
|
-
│ ├──
|
|
755
|
-
│ ├──
|
|
756
|
-
│ ├──
|
|
757
|
-
│ ├──
|
|
758
|
-
│ ├──
|
|
759
|
-
│ ├──
|
|
760
|
-
│ ├──
|
|
761
|
-
│
|
|
762
|
-
│ ├──
|
|
763
|
-
│ │ ├──
|
|
764
|
-
│ │ └──
|
|
765
|
-
│
|
|
766
|
-
│
|
|
767
|
-
│ │
|
|
768
|
-
│ │
|
|
769
|
-
│ │ ├──
|
|
770
|
-
│ │ ├──
|
|
771
|
-
│ │ ├──
|
|
772
|
-
│ │
|
|
773
|
-
│ ├──
|
|
774
|
-
│ │
|
|
775
|
-
│ │
|
|
776
|
-
│ │
|
|
777
|
-
│ │
|
|
778
|
-
│
|
|
779
|
-
│
|
|
780
|
-
├──
|
|
781
|
-
├──
|
|
782
|
-
|
|
1469
|
+
│ ├── composables/ # 甘特图组合式函数
|
|
1470
|
+
│ │ ├── LinkConfig.ts
|
|
1471
|
+
│ │ ├── PerformanceConfig.ts
|
|
1472
|
+
│ │ ├── useHorizontalVirtualScroll.ts
|
|
1473
|
+
│ │ └── useVirtualScroll.ts
|
|
1474
|
+
│ ├── config/ # 配置面板组件
|
|
1475
|
+
│ │ ├── CheckboxConfig.vue
|
|
1476
|
+
│ │ ├── ColorInput.vue
|
|
1477
|
+
│ │ ├── ColumnConfigPanel.vue
|
|
1478
|
+
│ │ ├── ConfigSection.vue
|
|
1479
|
+
│ │ ├── DatePicker.vue
|
|
1480
|
+
│ │ ├── GanttConfigPanel.vue
|
|
1481
|
+
│ │ ├── GanttThemeSelector.vue
|
|
1482
|
+
│ │ ├── LanguageSelector.vue
|
|
1483
|
+
│ │ ├── LinkConfigPanel.vue
|
|
1484
|
+
│ │ ├── LinkTypeColorConfig.vue
|
|
1485
|
+
│ │ ├── PathTypeSelector.vue
|
|
1486
|
+
│ │ ├── SliderInput.vue
|
|
1487
|
+
│ │ └── ThemeSelector.vue
|
|
1488
|
+
│ ├── core/ # 核心组件
|
|
1489
|
+
│ │ ├── Gantt.vue # 主组件
|
|
1490
|
+
│ │ └── SplitPane.vue # 分割面板
|
|
1491
|
+
│ ├── gantt.css # 甘特图样式
|
|
1492
|
+
│ ├── i18n/ # 国际化系统
|
|
1493
|
+
│ │ ├── index.ts # i18n 核心
|
|
1494
|
+
│ │ └── locales/ # 语言包
|
|
1495
|
+
│ │ ├── zh-CN.ts # 中文语言包
|
|
1496
|
+
│ │ ├── zh-TW.ts # 繁体中文语言包
|
|
1497
|
+
│ │ ├── en-US.ts # 英文语言包
|
|
1498
|
+
│ │ ├── ja-JP.ts # 日语语言包
|
|
1499
|
+
│ │ ├── ko-KR.ts # 韩语语言包
|
|
1500
|
+
│ │ ├── fr-FR.ts # 法语语言包
|
|
1501
|
+
│ │ ├── de-DE.ts # 德语语言包
|
|
1502
|
+
│ │ ├── es-ES.ts # 西班牙语语言包
|
|
1503
|
+
│ │ └── ru-RU.ts # 俄语语言包
|
|
1504
|
+
│ ├── links/ # 连线组件
|
|
1505
|
+
│ │ └── TaskLinks.vue # 任务连线
|
|
1506
|
+
│ ├── state/ # 状态管理
|
|
1507
|
+
│ │ ├── ShareState.ts # 共享状态
|
|
1508
|
+
│ │ ├── Store.ts # 状态存储
|
|
1509
|
+
│ │ └── Symbols.ts # 注入符号
|
|
1510
|
+
│ ├── task/ # 任务相关组件
|
|
1511
|
+
│ │ ├── TaskTable.vue # 任务表格
|
|
1512
|
+
│ │ ├── TaskHeader.vue # 任务表头
|
|
1513
|
+
│ │ ├── TaskContent.vue # 任务内容
|
|
1514
|
+
│ │ ├── TaskRow.vue # 任务行
|
|
1515
|
+
│ │ └── TaskRecursionRow.vue # 递归任务行
|
|
1516
|
+
│ ├── themes/ # 主题配置
|
|
1517
|
+
│ │ ├── GanttThemes.ts # 主题定义
|
|
1518
|
+
│ │ └── LiquidGlass.css # 液态玻璃主题
|
|
1519
|
+
│ ├── timeline/ # 时间轴组件
|
|
1520
|
+
│ │ ├── Bar.vue # 任务条
|
|
1521
|
+
│ │ ├── BarRecursionRow.vue # 递归任务条
|
|
1522
|
+
│ │ ├── Milestone.vue # 里程碑
|
|
1523
|
+
│ │ ├── RightTable.vue # 右侧甘特图区域
|
|
1524
|
+
│ │ ├── TableContent.vue # 表格内容
|
|
1525
|
+
│ │ ├── TimelineHeader.vue # 时间轴表头
|
|
1526
|
+
│ │ ├── composables/ # 时间轴组合式函数
|
|
1527
|
+
│ │ │ ├── useBarGeometry.ts
|
|
1528
|
+
│ │ │ ├── useBarTheme.ts
|
|
1529
|
+
│ │ │ ├── useHover.ts
|
|
1530
|
+
│ │ │ ├── useInteractions.ts
|
|
1531
|
+
│ │ │ └── useProgress.ts
|
|
1532
|
+
│ │ └── utils/ # 工具函数
|
|
1533
|
+
│ │ └── dateCalc.ts
|
|
1534
|
+
│ └── types/ # 类型定义
|
|
1535
|
+
│ ├── Types.ts # 甘特图类型
|
|
1536
|
+
│ └── ZodSchema.ts # 数据验证
|
|
1537
|
+
├── composables/ # 全局组合式函数
|
|
1538
|
+
│ ├── useCustomFields.ts # 自定义字段
|
|
1539
|
+
│ ├── useMessage.ts # 消息提示
|
|
1540
|
+
│ └── useTaskManagement.ts # 任务管理
|
|
1541
|
+
├── mock/ # 模拟数据
|
|
1542
|
+
│ └── mockData.ts # 示例数据
|
|
1543
|
+
├── services/ # 服务层
|
|
1544
|
+
│ └── taskApi.ts # 任务 API
|
|
1545
|
+
├── styles/ # 全局样式
|
|
1546
|
+
│ └── dialog-common.css # 对话框通用样式
|
|
1547
|
+
├── types/ # 类型定义
|
|
1548
|
+
│ └── task.ts # 任务类型
|
|
1549
|
+
├── App.vue # 示例应用
|
|
1550
|
+
├── index.ts # 导出入口
|
|
1551
|
+
├── main.ts # 应用入口
|
|
1552
|
+
├── style.css # 全局样式
|
|
1553
|
+
└── vite-env.d.ts # Vite 环境类型
|
|
783
1554
|
```
|
|
784
1555
|
|
|
785
1556
|
## 完整示例
|
|
@@ -809,7 +1580,7 @@ MIT
|
|
|
809
1580
|
|
|
810
1581
|
<div id="english-documentation"></div>
|
|
811
1582
|
|
|
812
|
-
<details>
|
|
1583
|
+
<details open>
|
|
813
1584
|
<summary><h2>🇺🇸 English Documentation</h2></summary>
|
|
814
1585
|
|
|
815
1586
|
A feature-rich, highly customizable Vue 3 Gantt chart component that supports task management, dependency relationships, multiple view modes, and theme switching.
|
|
@@ -820,10 +1591,16 @@ A feature-rich, highly customizable Vue 3 Gantt chart component that supports ta
|
|
|
820
1591
|
<img src="https://img.shields.io/badge/Vite-6.2.0-646CFF?style=for-the-badge&logo=vite&logoColor=white" alt="Vite">
|
|
821
1592
|
</div>
|
|
822
1593
|
|
|
823
|
-
**Note**: For better reading experience, you can also view the [separate English README file](README.en-US.md).
|
|
824
|
-
|
|
825
1594
|
## Interface Preview
|
|
826
1595
|
|
|
1596
|
+
<div align="center">
|
|
1597
|
+
<img src="https://github.com/user-attachments/assets/34562bf8-0709-44aa-a05d-6e970ea8b57f" alt="Vue3 Gantt Chart - Light Theme" />
|
|
1598
|
+
<p><em>Light Theme - Complete Task Management Interface</em></p>
|
|
1599
|
+
|
|
1600
|
+
<img src="https://github.com/user-attachments/assets/d6a60ba1-9f5b-479a-b402-68014ec7c935" alt="Vue3 Gantt Chart - Dark Theme" />
|
|
1601
|
+
<p><em>Dark Theme - Eye-friendly Mode</em></p>
|
|
1602
|
+
</div>
|
|
1603
|
+
|
|
827
1604
|
```
|
|
828
1605
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
829
1606
|
│ Vue3 Gantt Professional Component │
|
|
@@ -839,39 +1616,1780 @@ A feature-rich, highly customizable Vue 3 Gantt chart component that supports ta
|
|
|
839
1616
|
└─────────────────┴───────────────────────────────────────────────────────────┘
|
|
840
1617
|
```
|
|
841
1618
|
|
|
842
|
-
**Key
|
|
843
|
-
- 🎯 Left task list + Right Gantt
|
|
844
|
-
- 📊 Visual progress bars
|
|
845
|
-
- 🔗
|
|
846
|
-
- 🎨 Multi-
|
|
847
|
-
- 🖱️ Drag
|
|
848
|
-
- 🌍
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
- **
|
|
857
|
-
- **
|
|
858
|
-
- **
|
|
859
|
-
- **
|
|
860
|
-
- **
|
|
861
|
-
|
|
862
|
-
###
|
|
863
|
-
-
|
|
864
|
-
-
|
|
865
|
-
-
|
|
866
|
-
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
-
|
|
870
|
-
-
|
|
871
|
-
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
1619
|
+
**Key Highlights:**
|
|
1620
|
+
- 🎯 **Dual-Column Layout** - Left task list + Right Gantt timeline, clear information at a glance
|
|
1621
|
+
- 📊 **Visual Progress** - Real-time progress bars with drag-to-adjust completion
|
|
1622
|
+
- 🔗 **Smart Dependencies** - Four dependency types (FS/SS/FF/SF) with auto-drawn links
|
|
1623
|
+
- 🎨 **Multi-Theme** - 5 built-in themes, dark mode and custom theme support
|
|
1624
|
+
- 🖱️ **Rich Interactions** - Drag move, resize, parent-child task linkage
|
|
1625
|
+
- 🌍 **Internationalization** - Built-in 8 languages, easily extensible
|
|
1626
|
+
- ⚡ **High Performance** - Virtual scrolling, handles massive task data effortlessly
|
|
1627
|
+
- 💎 **Milestones** - Diamond markers for key nodes with dependency support
|
|
1628
|
+
|
|
1629
|
+
## ✨ Core Features
|
|
1630
|
+
|
|
1631
|
+
### 📅 Multiple View Modes
|
|
1632
|
+
Five time granularities for different scenarios:
|
|
1633
|
+
- **Quarter View** - Ultra-long-term project planning, displayed by month
|
|
1634
|
+
- **Month View** - Long-term project planning, displayed by day
|
|
1635
|
+
- **Week View** - Medium-term project tracking, displayed by week
|
|
1636
|
+
- **Day View** - Short-term task management, supports full day/half day sub-modes
|
|
1637
|
+
- **Hour View** - Fine task scheduling, supports hour/30min/15min sub-modes
|
|
1638
|
+
|
|
1639
|
+
### 🔗 Task Dependency Management
|
|
1640
|
+
- **Finish-to-Start (FS)** - Successor task starts after predecessor finishes
|
|
1641
|
+
- **Start-to-Start (SS)** - Both tasks start simultaneously
|
|
1642
|
+
- **Finish-to-Finish (FF)** - Both tasks finish simultaneously
|
|
1643
|
+
- **Start-to-Finish (SF)** - Predecessor finishes after successor starts
|
|
1644
|
+
|
|
1645
|
+
### 💎 Milestone Features
|
|
1646
|
+
- Diamond icon markers for project key nodes
|
|
1647
|
+
- Support as dependency source and target
|
|
1648
|
+
- Auto-detect (start time = end time) or manual marking
|
|
1649
|
+
|
|
1650
|
+
### 🎨 Theme System
|
|
1651
|
+
- 5 beautiful built-in themes (Metro/Dark/Modern/Classic/Colorful)
|
|
1652
|
+
- Dark mode support, eye-friendly
|
|
1653
|
+
- Complete CSS variable support, easy customization
|
|
1654
|
+
- Theme settings auto-saved to browser
|
|
1655
|
+
|
|
1656
|
+
### 🌍 Internationalization
|
|
1657
|
+
- Built-in 8 languages (CN/EN/JP/KR/FR/DE/ES/RU)
|
|
1658
|
+
- Instant switching, no page refresh needed
|
|
1659
|
+
- All UI elements fully translated
|
|
1660
|
+
- Timeline headers auto-localized
|
|
1661
|
+
- Easy to extend new languages
|
|
1662
|
+
|
|
1663
|
+
### 🖱️ Interactive Operations
|
|
1664
|
+
- **Drag Move** - Modify task start and end dates
|
|
1665
|
+
- **Resize** - Drag edges to adjust task duration
|
|
1666
|
+
- **Progress Adjust** - Drag triangle slider to adjust completion
|
|
1667
|
+
- **Parent-Child Linkage** - Child tasks follow when parent moves
|
|
1668
|
+
- **Split Panel** - Adjustable left-right area ratio
|
|
1669
|
+
|
|
1670
|
+
### ⚡ Performance Optimization
|
|
1671
|
+
- Virtual scroll rendering, supports massive task data
|
|
1672
|
+
- Throttled updates, avoids frequent redraws
|
|
1673
|
+
- Cached computations, improves response speed
|
|
1674
|
+
- On-demand link rendering, optimized drawing performance
|
|
1675
|
+
|
|
1676
|
+
### 📝 Custom Fields
|
|
1677
|
+
- **Multiple Field Types** - Supports text, number, date, dropdown selection field types
|
|
1678
|
+
- **Flexible Configuration** - Add any number of custom fields to tasks
|
|
1679
|
+
- **Form Validation** - Built-in field validation rules ensure data validity
|
|
1680
|
+
- **Local Storage** - Field configuration automatically saved to browser, persists after refresh
|
|
1681
|
+
- **Dynamic Management** - Add, edit, delete custom fields at runtime
|
|
1682
|
+
|
|
1683
|
+
### 💬 Message Toast
|
|
1684
|
+
- **Three Alert Types** - Success, error, warning for different scenarios
|
|
1685
|
+
- **Auto Dismiss** - Messages automatically disappear without manual closing
|
|
1686
|
+
- **Elegant Animation** - Smooth enter and exit animation effects
|
|
1687
|
+
- **Multi-language Support** - Alert text automatically switches with language settings
|
|
1688
|
+
|
|
1689
|
+
### 🗑️ Delete Confirmation
|
|
1690
|
+
- **Safe Deletion** - Confirmation dialog before task deletion prevents accidental operations
|
|
1691
|
+
- **Cascade Delete** - When deleting parent task, automatically prompts that all subtasks will be deleted
|
|
1692
|
+
- **Friendly Prompts** - Clear warning messages inform users about deletion impact scope
|
|
1693
|
+
|
|
1694
|
+
### 🎛️ Configuration Panels
|
|
1695
|
+
- **Link Style Configuration** - Customize task link path type, color, width, dashed style, arrow settings
|
|
1696
|
+
- **Parent-Child Relationship Style** - Configure parent-child task connection line styles
|
|
1697
|
+
- **Column Display Settings** - Flexibly control task list column show/hide
|
|
1698
|
+
- **One-click Reset** - Quickly restore default configuration
|
|
1699
|
+
|
|
1700
|
+
### 🌲 Tree Task Structure
|
|
1701
|
+
- **Hierarchy Display** - Clear tree structure showing task parent-child relationships
|
|
1702
|
+
- **Collapse/Expand** - Support collapsing/expanding subtasks to simplify view
|
|
1703
|
+
- **Connection Lines** - Visual connection lines showing hierarchy relationships
|
|
1704
|
+
- **Quick Operations** - Inline buttons for quickly adding/deleting subtasks
|
|
1705
|
+
- **Hover Highlight** - Mouse hover highlights current task row
|
|
1706
|
+
|
|
1707
|
+
## 🚀 Installation
|
|
1708
|
+
|
|
1709
|
+
### Option 1: Install via npm (Recommended)
|
|
1710
|
+
|
|
1711
|
+
```bash
|
|
1712
|
+
# Using npm
|
|
1713
|
+
npm install @lee576/vue3-gantt
|
|
1714
|
+
|
|
1715
|
+
# Or using yarn
|
|
1716
|
+
yarn add @lee576/vue3-gantt
|
|
1717
|
+
|
|
1718
|
+
# Or using pnpm
|
|
1719
|
+
pnpm add @lee576/vue3-gantt
|
|
1720
|
+
```
|
|
1721
|
+
|
|
1722
|
+
### Option 2: Build from Source
|
|
1723
|
+
|
|
1724
|
+
```bash
|
|
1725
|
+
# Clone repository
|
|
1726
|
+
git clone https://github.com/lee576/vue3-gantt.git
|
|
1727
|
+
cd vue3-gantt
|
|
1728
|
+
|
|
1729
|
+
# Install dependencies
|
|
1730
|
+
npm install
|
|
1731
|
+
|
|
1732
|
+
# Start development server
|
|
1733
|
+
npm run dev
|
|
1734
|
+
```
|
|
1735
|
+
|
|
1736
|
+
## 📚 Quick Start
|
|
1737
|
+
|
|
1738
|
+
### 1️⃣ Import Component
|
|
1739
|
+
|
|
1740
|
+
```typescript
|
|
1741
|
+
import { createApp } from 'vue';
|
|
1742
|
+
import Gantt from '@lee576/vue3-gantt';
|
|
1743
|
+
import '@lee576/vue3-gantt/style.css';
|
|
1744
|
+
|
|
1745
|
+
const app = createApp(App);
|
|
1746
|
+
app.use(Gantt); // Global registration
|
|
1747
|
+
```
|
|
1748
|
+
|
|
1749
|
+
Or import in component:
|
|
1750
|
+
|
|
1751
|
+
```vue
|
|
1752
|
+
<script setup lang="ts">
|
|
1753
|
+
import { ref } from 'vue';
|
|
1754
|
+
import Gantt, {
|
|
1755
|
+
type DataConfig,
|
|
1756
|
+
type StyleConfig,
|
|
1757
|
+
type EventConfig,
|
|
1758
|
+
LinkType
|
|
1759
|
+
} from '@lee576/vue3-gantt';
|
|
1760
|
+
import '@lee576/vue3-gantt/style.css';
|
|
1761
|
+
</script>
|
|
1762
|
+
```
|
|
1763
|
+
|
|
1764
|
+
### 2️⃣ Configure Container Height (Important!)
|
|
1765
|
+
|
|
1766
|
+
> ⚠️ **Important**: The component **must have an explicit container height** to display properly.
|
|
1767
|
+
|
|
1768
|
+
**Recommended methods (choose one):**
|
|
1769
|
+
|
|
1770
|
+
```vue
|
|
1771
|
+
<!-- Method 1: Use viewport height (Easiest) -->
|
|
1772
|
+
<template>
|
|
1773
|
+
<div style="height: 100vh;">
|
|
1774
|
+
<gantt :dataConfig="dataConfig" :styleConfig="styleConfig" />
|
|
1775
|
+
</div>
|
|
1776
|
+
</template>
|
|
1777
|
+
|
|
1778
|
+
<!-- Method 2: Use fixed height -->
|
|
1779
|
+
<template>
|
|
1780
|
+
<div style="height: 800px;">
|
|
1781
|
+
<gantt :dataConfig="dataConfig" :styleConfig="styleConfig" />
|
|
1782
|
+
</div>
|
|
1783
|
+
</template>
|
|
1784
|
+
|
|
1785
|
+
<!-- Method 3: Flex layout -->
|
|
1786
|
+
<template>
|
|
1787
|
+
<div style="display: flex; flex-direction: column; height: 100vh;">
|
|
1788
|
+
<div>Header</div>
|
|
1789
|
+
<div style="flex: 1;"> <!-- Auto-fill remaining space -->
|
|
1790
|
+
<gantt :dataConfig="dataConfig" :styleConfig="styleConfig" />
|
|
1791
|
+
</div>
|
|
1792
|
+
</div>
|
|
1793
|
+
</template>
|
|
1794
|
+
```
|
|
1795
|
+
|
|
1796
|
+
<details>
|
|
1797
|
+
<summary>💡 Why set height?</summary>
|
|
1798
|
+
|
|
1799
|
+
The component uses `height: 100%` internally. According to CSS specifications, percentage height requires the parent element to have an explicit height to calculate. Without a height on the parent container, the component will collapse.
|
|
1800
|
+
|
|
1801
|
+
**Solutions:**
|
|
1802
|
+
- Use `100vh` (viewport height)
|
|
1803
|
+
- Use fixed pixel value (e.g., `800px`)
|
|
1804
|
+
- Use Flex layout's `flex: 1`
|
|
1805
|
+
- Configure `html, body { height: 100%; }` then use `100%`
|
|
1806
|
+
|
|
1807
|
+
</details>
|
|
1808
|
+
|
|
1809
|
+
### 3️⃣ Basic Configuration
|
|
1810
|
+
|
|
1811
|
+
```vue
|
|
1812
|
+
<template>
|
|
1813
|
+
<div style="height: 100vh;">
|
|
1814
|
+
<gantt
|
|
1815
|
+
:dataConfig="dataConfig"
|
|
1816
|
+
:styleConfig="styleConfig"
|
|
1817
|
+
:eventConfig="eventConfig"
|
|
1818
|
+
/>
|
|
1819
|
+
</div>
|
|
1820
|
+
</template>
|
|
1821
|
+
|
|
1822
|
+
<script setup lang="ts">
|
|
1823
|
+
import { ref, onMounted } from 'vue';
|
|
1824
|
+
import dayjs from 'dayjs';
|
|
1825
|
+
import Gantt, {
|
|
1826
|
+
type DataConfig,
|
|
1827
|
+
type StyleConfig,
|
|
1828
|
+
type EventConfig,
|
|
1829
|
+
LinkType
|
|
1830
|
+
} from '@lee576/vue3-gantt';
|
|
1831
|
+
import '@lee576/vue3-gantt/style.css';
|
|
1832
|
+
|
|
1833
|
+
// 🎨 Style Configuration
|
|
1834
|
+
const styleConfig = ref<StyleConfig>({
|
|
1835
|
+
headersHeight: 100, // Header height
|
|
1836
|
+
rowHeight: 60, // Row height
|
|
1837
|
+
setBarColor: (row) => {
|
|
1838
|
+
// Custom task bar colors
|
|
1839
|
+
const colorMap = { 'urgent': '#ef4444', 'important': '#3b82f6', 'normal': '#6b7280' };
|
|
1840
|
+
return colorMap[row.level] ?? '#000';
|
|
1841
|
+
}
|
|
1842
|
+
});
|
|
1843
|
+
|
|
1844
|
+
// 📊 Data Configuration
|
|
1845
|
+
const dataConfig = ref<DataConfig>({
|
|
1846
|
+
queryStartDate: dayjs().startOf('month').format('YYYY-MM-DD'),
|
|
1847
|
+
queryEndDate: dayjs().endOf('month').format('YYYY-MM-DD'),
|
|
1848
|
+
dataSource: [],
|
|
1849
|
+
dependencies: [],
|
|
1850
|
+
mapFields: {
|
|
1851
|
+
id: 'id',
|
|
1852
|
+
parentId: 'pid',
|
|
1853
|
+
task: 'taskNo',
|
|
1854
|
+
priority: 'level',
|
|
1855
|
+
startdate: 'start_date',
|
|
1856
|
+
enddate: 'end_date',
|
|
1857
|
+
takestime: 'spend_time',
|
|
1858
|
+
progress: 'job_progress'
|
|
1859
|
+
},
|
|
1860
|
+
taskHeaders: [
|
|
1861
|
+
{ title: 'No.', width: 80, property: 'no', show: true },
|
|
1862
|
+
{ title: 'Task Name', width: 200, property: 'task', show: true },
|
|
1863
|
+
{ title: 'Priority', width: 90, property: 'priority', show: true },
|
|
1864
|
+
{ title: 'Start Date', width: 150, property: 'startdate', show: true },
|
|
1865
|
+
{ title: 'End Date', width: 150, property: 'enddate', show: true },
|
|
1866
|
+
]
|
|
1867
|
+
});
|
|
1868
|
+
|
|
1869
|
+
// ⚡ Event Configuration
|
|
1870
|
+
const eventConfig = ref<EventConfig>({
|
|
1871
|
+
queryTask: async (startDate, endDate, mode) => {
|
|
1872
|
+
// Query task data
|
|
1873
|
+
const tasks = await fetchTasks(startDate, endDate);
|
|
1874
|
+
dataConfig.value.dataSource = tasks;
|
|
1875
|
+
},
|
|
1876
|
+
barDate: (id, startDate, endDate) => {
|
|
1877
|
+
console.log('Task date changed', { id, startDate, endDate });
|
|
1878
|
+
},
|
|
1879
|
+
updateProgress: (detail) => {
|
|
1880
|
+
console.log('Progress updated', detail);
|
|
1881
|
+
}
|
|
1882
|
+
});
|
|
1883
|
+
|
|
1884
|
+
// Initialize and load data
|
|
1885
|
+
onMounted(() => {
|
|
1886
|
+
const start = dayjs().startOf('month').format('YYYY-MM-DD');
|
|
1887
|
+
const end = dayjs().endOf('month').format('YYYY-MM-DD');
|
|
1888
|
+
eventConfig.value.queryTask?.(start, end, 'month');
|
|
1889
|
+
});
|
|
1890
|
+
</script>
|
|
1891
|
+
```
|
|
1892
|
+
|
|
1893
|
+
## 📖 Configuration Guide
|
|
1894
|
+
|
|
1895
|
+
## Configuration Details
|
|
1896
|
+
|
|
1897
|
+
### StyleConfig
|
|
1898
|
+
|
|
1899
|
+
| Property | Type | Default | Description |
|
|
1900
|
+
|----------|------|---------|-------------|
|
|
1901
|
+
| headersHeight | number | 100 | Header area height (pixels) |
|
|
1902
|
+
| rowHeight | number | 60 | Row height (pixels) |
|
|
1903
|
+
| setBarColor | function | - | Callback function for custom task bar colors |
|
|
1904
|
+
|
|
1905
|
+
### DataConfig
|
|
1906
|
+
|
|
1907
|
+
| Property | Type | Description |
|
|
1908
|
+
|----------|------|-------------|
|
|
1909
|
+
| queryStartDate | string | Query start date (YYYY-MM-DD) |
|
|
1910
|
+
| queryEndDate | string | Query end date (YYYY-MM-DD) |
|
|
1911
|
+
| dataSource | array | Task data source |
|
|
1912
|
+
| dependencies | array | Task dependencies |
|
|
1913
|
+
| mapFields | object | Field mapping configuration |
|
|
1914
|
+
| taskHeaders | array | Left task table column configuration |
|
|
1915
|
+
|
|
1916
|
+
#### mapFields Field Mapping
|
|
1917
|
+
|
|
1918
|
+
```typescript
|
|
1919
|
+
{
|
|
1920
|
+
id: 'id', // Task ID field
|
|
1921
|
+
parentId: 'pid', // Parent task ID field (for hierarchy)
|
|
1922
|
+
task: 'taskNo', // Task name field
|
|
1923
|
+
priority: 'level', // Priority field
|
|
1924
|
+
startdate: 'start_date', // Start date field
|
|
1925
|
+
enddate: 'end_date', // End date field
|
|
1926
|
+
takestime: 'spend_time', // Duration field
|
|
1927
|
+
progress: 'job_progress' // Progress field (0-1)
|
|
1928
|
+
}
|
|
1929
|
+
```
|
|
1930
|
+
|
|
1931
|
+
#### taskHeaders Header Configuration
|
|
1932
|
+
|
|
1933
|
+
```typescript
|
|
1934
|
+
{
|
|
1935
|
+
title: string; // Column title
|
|
1936
|
+
width: number; // Column width
|
|
1937
|
+
property: string; // Corresponds to property name in mapFields
|
|
1938
|
+
show: boolean; // Whether to display
|
|
1939
|
+
}
|
|
1940
|
+
```
|
|
1941
|
+
|
|
1942
|
+
|
|
1943
|
+
### EventConfig
|
|
1944
|
+
|
|
1945
|
+
| Event | Parameters | Description |
|
|
1946
|
+
|-------|------------|-------------|
|
|
1947
|
+
| addRootTask | (row) | Triggered when adding a root task |
|
|
1948
|
+
| addSubTask | (task) | Triggered when adding a subtask |
|
|
1949
|
+
| removeTask | (task) | Triggered when removing a task |
|
|
1950
|
+
| editTask | (task) | Triggered when editing a task |
|
|
1951
|
+
| queryTask | (startDate, endDate, mode) | Triggered when querying tasks |
|
|
1952
|
+
| barDate | (id, startDate, endDate) | Triggered when task date changes |
|
|
1953
|
+
| allowChangeTaskDate | (allow) | Whether task date modification is allowed |
|
|
1954
|
+
| updateProgress | (detail) | Triggered when progress is updated |
|
|
1955
|
+
|
|
1956
|
+
#### updateProgress Event Details
|
|
1957
|
+
|
|
1958
|
+
```typescript
|
|
1959
|
+
interface ProgressUpdateDetail {
|
|
1960
|
+
taskId: any; // Task ID
|
|
1961
|
+
oldProgress: number; // Old progress value (0-1)
|
|
1962
|
+
newProgress: number; // New progress value (0-1)
|
|
1963
|
+
task: object; // Complete task object
|
|
1964
|
+
}
|
|
1965
|
+
```
|
|
1966
|
+
|
|
1967
|
+
## Task Data Format
|
|
1968
|
+
|
|
1969
|
+
### Regular Task
|
|
1970
|
+
|
|
1971
|
+
```typescript
|
|
1972
|
+
{
|
|
1973
|
+
id: '1', // Task ID
|
|
1974
|
+
pid: '0', // Parent task ID, '0' means root task
|
|
1975
|
+
taskNo: 'Project Planning Phase', // Task name
|
|
1976
|
+
level: 'Important', // Priority
|
|
1977
|
+
start_date: '2024-12-01 08:00:00', // Start time
|
|
1978
|
+
end_date: '2024-12-06 18:00:00', // End time
|
|
1979
|
+
job_progress: '0.85', // Progress (0-1)
|
|
1980
|
+
spend_time: null // Duration (auto-calculated)
|
|
1981
|
+
}
|
|
1982
|
+
```
|
|
1983
|
+
|
|
1984
|
+
### Milestone Task
|
|
1985
|
+
|
|
1986
|
+
Milestones are key project checkpoints, displayed with diamond icons. The key characteristic is **start date equals end date**:
|
|
1987
|
+
|
|
1988
|
+
```typescript
|
|
1989
|
+
{
|
|
1990
|
+
id: 'milestone-1', // Milestone ID
|
|
1991
|
+
pid: '0', // Parent task ID
|
|
1992
|
+
taskNo: '🎯 Requirements Complete', // Milestone name
|
|
1993
|
+
level: 'Urgent', // Priority
|
|
1994
|
+
start_date: '2024-12-02 18:00:00', // Start time
|
|
1995
|
+
end_date: '2024-12-02 18:00:00', // End time (same as start)
|
|
1996
|
+
job_progress: '1.0', // Milestones are usually 100%
|
|
1997
|
+
spend_time: null,
|
|
1998
|
+
type: 'milestone' // Optional: explicitly mark as milestone
|
|
1999
|
+
}
|
|
2000
|
+
```
|
|
2001
|
+
|
|
2002
|
+
**Milestone Recognition Rules**:
|
|
2003
|
+
1. **Auto-detection**: Automatically displayed as diamond when `start_date === end_date`
|
|
2004
|
+
2. **Explicit marking**: Set `type: 'milestone'` field
|
|
2005
|
+
3. **Custom function**: Custom logic via `styleConfig.setTaskType`
|
|
2006
|
+
|
|
2007
|
+
## Task Dependencies
|
|
2008
|
+
|
|
2009
|
+
```
|
|
2010
|
+
Finish-Start (FS) Start-Start (SS) Finish-Finish (FF) Start-Finish (SF)
|
|
2011
|
+
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
|
|
2012
|
+
│ Task A │──┐ │ Task A │──┐ │ Task A │──┐ │ Task A │◄─┐
|
|
2013
|
+
└─────────┘ │ └─────────┘ │ └─────────┘ │ └─────────┘ │
|
|
2014
|
+
▼ ▼ ▼ │
|
|
2015
|
+
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
|
|
2016
|
+
│ Task B │ │ Task B │ │ Task B │ │ Task B │
|
|
2017
|
+
└─────────┘ └─────────┘ └─────────┘ └─────────┘
|
|
2018
|
+
B starts after A and B start A and B finish B starts
|
|
2019
|
+
A finishes together together before A ends
|
|
2020
|
+
```
|
|
2021
|
+
|
|
2022
|
+
### Dependency Types
|
|
2023
|
+
|
|
2024
|
+
| Type | Enum | Description |
|
|
2025
|
+
|------|------|-------------|
|
|
2026
|
+
| Finish-Start (FS) | FINISH_TO_START | Successor task starts after predecessor finishes |
|
|
2027
|
+
| Start-Start (SS) | START_TO_START | Tasks start simultaneously |
|
|
2028
|
+
| Finish-Finish (FF) | FINISH_TO_FINISH | Tasks finish simultaneously |
|
|
2029
|
+
| Start-Finish (SF) | START_TO_FINISH | Predecessor finishes after successor starts |
|
|
2030
|
+
|
|
2031
|
+
### Configuration Example
|
|
2032
|
+
|
|
2033
|
+
#### Regular Task Dependencies
|
|
2034
|
+
|
|
2035
|
+
```typescript
|
|
2036
|
+
import { LinkType } from './components/gantt/Types';
|
|
2037
|
+
|
|
2038
|
+
dependencies: [
|
|
2039
|
+
// Task 2 starts after Task 1 finishes
|
|
2040
|
+
{ sourceTaskId: '1', targetTaskId: '2', type: LinkType.FINISH_TO_START },
|
|
2041
|
+
|
|
2042
|
+
// Task 3 and Task 4 start together
|
|
2043
|
+
{ sourceTaskId: '3', targetTaskId: '4', type: LinkType.START_TO_START },
|
|
2044
|
+
|
|
2045
|
+
// Task 5 and Task 6 must finish together
|
|
2046
|
+
{ sourceTaskId: '5', targetTaskId: '6', type: LinkType.FINISH_TO_FINISH },
|
|
2047
|
+
]
|
|
2048
|
+
```
|
|
2049
|
+
|
|
2050
|
+
#### Milestone Dependencies
|
|
2051
|
+
|
|
2052
|
+
Milestones support being **source** or **target** in dependency relationships:
|
|
2053
|
+
|
|
2054
|
+
```typescript
|
|
2055
|
+
dependencies: [
|
|
2056
|
+
// Task completion → Milestone
|
|
2057
|
+
{ sourceTaskId: 'task-5', targetTaskId: 'milestone-1', type: LinkType.FINISH_TO_START },
|
|
2058
|
+
|
|
2059
|
+
// Milestone → Task starts
|
|
2060
|
+
{ sourceTaskId: 'milestone-1', targetTaskId: 'task-6', type: LinkType.FINISH_TO_START },
|
|
2061
|
+
|
|
2062
|
+
// Multiple tasks → Same milestone
|
|
2063
|
+
{ sourceTaskId: 'frontend-dev', targetTaskId: 'milestone-2', type: LinkType.FINISH_TO_START },
|
|
2064
|
+
{ sourceTaskId: 'backend-dev', targetTaskId: 'milestone-2', type: LinkType.FINISH_TO_START },
|
|
2065
|
+
]
|
|
2066
|
+
```
|
|
2067
|
+
|
|
2068
|
+
## View Modes
|
|
2069
|
+
|
|
2070
|
+
| Mode | Time Unit | Header Example | Use Case |
|
|
2071
|
+
|------|-----------|----------------|----------|
|
|
2072
|
+
| 📆 **Quarter** | Month | `2024-Q1 2024-Q2 2024-Q3 ...` | Ultra long-term project planning |
|
|
2073
|
+
| 🗓️ **Month** | Day | `01 02 03 04 05 ...` | Long-term project planning |
|
|
2074
|
+
| 📅 **Day** | Day | `Mon Tue Wed ...` | Short-term task management |
|
|
2075
|
+
| 📊 **Week** | Week | `W50 W51 W52 ...` | Mid-term project tracking |
|
|
2076
|
+
| ⏰ **Hour** | Hour | `08 09 10 11 12 ...` | Precise task scheduling |
|
|
2077
|
+
|
|
2078
|
+
The component supports five time granularity views:
|
|
2079
|
+
|
|
2080
|
+
| Mode | Description | Sub-modes | Use Case |
|
|
2081
|
+
|------|-------------|-----------|----------|
|
|
2082
|
+
| Quarter | Display by month, quarter unit | - | Ultra long-term project planning |
|
|
2083
|
+
| Month | Display by day, month unit | - | Long-term project planning |
|
|
2084
|
+
| Day | Display by day, precise to day | Full day / Half day | Short-term task management |
|
|
2085
|
+
| Week | Display by week | - | Mid-term project tracking |
|
|
2086
|
+
| Hour | Display by hour | Hour / 30min / 15min | Precise task scheduling |
|
|
2087
|
+
|
|
2088
|
+
### View Mode Switching
|
|
2089
|
+
|
|
2090
|
+
The component provides view mode switching buttons at the top. Click to switch between different view modes.
|
|
2091
|
+
|
|
2092
|
+
### Sub-mode Details
|
|
2093
|
+
|
|
2094
|
+
**Day View Sub-modes:**
|
|
2095
|
+
- **Full day** - Each day displays as a complete time segment
|
|
2096
|
+
- **Half day** - Each day is divided into morning and afternoon time segments
|
|
2097
|
+
|
|
2098
|
+
**Hour View Sub-modes:**
|
|
2099
|
+
- **Hour** - Each hour displays as a time segment
|
|
2100
|
+
- **30min** - Each hour is divided into two 30-minute segments
|
|
2101
|
+
- **15min** - Each hour is divided into four 15-minute segments
|
|
2102
|
+
|
|
2103
|
+
## Theme System
|
|
2104
|
+
|
|
2105
|
+
| Theme | Primary Color | Style Features |
|
|
2106
|
+
|-------|---------------|----------------|
|
|
2107
|
+
| 🔷 **Metro** | `#0078d4` | Microsoft Metro design language, professional metallic texture |
|
|
2108
|
+
| 🌙 **Dark** | `#00d4ff` | Eye-friendly dark theme, suitable for extended use |
|
|
2109
|
+
| ✨ **Modern** | `#6366f1` | Clean modern design, refreshing and comfortable |
|
|
2110
|
+
| 💼 **Classic** | `#2563eb` | Traditional business style, stable and dignified |
|
|
2111
|
+
| 🎨 **Colorful** | `#f59e0b` | Vibrant colorful theme, full of vitality |
|
|
2112
|
+
| 🍎 **Apple** | `#007aff` | Minimalist elegant macOS style, smooth and natural |
|
|
2113
|
+
| 💧 **Liquid Glass** | `#007aff` | iOS 26 liquid glass effect, translucent flowing texture |
|
|
2114
|
+
|
|
2115
|
+
### Built-in Themes
|
|
2116
|
+
|
|
2117
|
+
| Theme ID | Name | Description |
|
|
2118
|
+
|----------|------|-------------|
|
|
2119
|
+
| metro | Metro | Microsoft Metro design language |
|
|
2120
|
+
| dark | Dark Mode | Eye-friendly dark theme |
|
|
2121
|
+
| modern | Modern | Clean modern design |
|
|
2122
|
+
| classic | Classic | Traditional business style |
|
|
2123
|
+
| colorful | Colorful | Vibrant colorful theme |
|
|
2124
|
+
| apple | Apple | Minimalist elegant macOS style |
|
|
2125
|
+
| liquidGlass | Liquid Glass | iOS 26 liquid glass effect |
|
|
2126
|
+
|
|
2127
|
+
### Switching Themes
|
|
2128
|
+
|
|
2129
|
+
A theme selector is provided in the top right corner of the component. Click to switch themes. Theme settings are automatically saved to localStorage.
|
|
2130
|
+
|
|
2131
|
+
### Custom Theme CSS Variables
|
|
2132
|
+
|
|
2133
|
+
```css
|
|
2134
|
+
:root {
|
|
2135
|
+
--primary: #0078d4; /* Primary color */
|
|
2136
|
+
--primary-dark: #106ebe; /* Primary color dark */
|
|
2137
|
+
--primary-light: #1084d8; /* Primary color light */
|
|
2138
|
+
--bg-content: #ffffff; /* Content background color */
|
|
2139
|
+
--bg-metal-light: linear-gradient(145deg, #ffffff, #f5f5f5);
|
|
2140
|
+
--bg-metal-normal: linear-gradient(145deg, #f5f5f5, #e8e8e8);
|
|
2141
|
+
--border: #d0d0d0; /* Border color */
|
|
2142
|
+
--text-primary: #333333; /* Primary text color */
|
|
2143
|
+
--text-secondary: #666666; /* Secondary text color */
|
|
2144
|
+
--row-hover: #FFF3A1; /* Row hover color */
|
|
2145
|
+
--font-family: 'Segoe UI', sans-serif;
|
|
2146
|
+
}
|
|
2147
|
+
```
|
|
2148
|
+
|
|
2149
|
+
## Custom Fields
|
|
2150
|
+
|
|
2151
|
+
The component supports powerful custom field functionality, allowing you to add any number of custom fields to tasks to meet different project personalization needs.
|
|
2152
|
+
|
|
2153
|
+
### Features
|
|
2154
|
+
|
|
2155
|
+
- **Multiple Field Types** - Text, number, date, dropdown selection
|
|
2156
|
+
- **Dynamic Management** - Add, edit, delete fields at runtime
|
|
2157
|
+
- **Form Validation** - Built-in validation rules ensure data validity
|
|
2158
|
+
- **Local Storage** - Field configuration automatically saved to browser
|
|
2159
|
+
- **Task Binding** - Custom field values associated with task data
|
|
2160
|
+
|
|
2161
|
+
### Field Types
|
|
2162
|
+
|
|
2163
|
+
| Type | Description | Example Value |
|
|
2164
|
+
|------|-------------|---------------|
|
|
2165
|
+
| Text | Single-line text input | "Project ID: PRJ-001" |
|
|
2166
|
+
| Number | Numeric input, supports decimals | 100.5 |
|
|
2167
|
+
| Date | Date picker | "2024-12-01" |
|
|
2168
|
+
| Dropdown | Predefined option list | "High Priority" |
|
|
2169
|
+
|
|
2170
|
+
### Usage
|
|
2171
|
+
|
|
2172
|
+
#### 1. Open Custom Field Management
|
|
2173
|
+
|
|
2174
|
+
Click the "Custom Fields" button in the Gantt chart toolbar to open the field management dialog.
|
|
2175
|
+
|
|
2176
|
+
#### 2. Add Custom Field
|
|
2177
|
+
|
|
2178
|
+
```typescript
|
|
2179
|
+
// Example: Add an "Owner" field
|
|
2180
|
+
const customField = {
|
|
2181
|
+
id: 'field-1',
|
|
2182
|
+
name: 'Owner',
|
|
2183
|
+
type: 'text', // text | number | date | select
|
|
2184
|
+
required: false, // Whether required
|
|
2185
|
+
options: [] // Options for dropdown selection
|
|
2186
|
+
};
|
|
2187
|
+
```
|
|
2188
|
+
|
|
2189
|
+
#### 3. Use Custom Fields in Tasks
|
|
2190
|
+
|
|
2191
|
+
Custom field values are stored in the task's `customFieldValues` field:
|
|
2192
|
+
|
|
2193
|
+
```typescript
|
|
2194
|
+
{
|
|
2195
|
+
id: '1',
|
|
2196
|
+
taskNo: 'Project Planning',
|
|
2197
|
+
start_date: '2024-12-01',
|
|
2198
|
+
end_date: '2024-12-06',
|
|
2199
|
+
job_progress: '0.85',
|
|
2200
|
+
customFieldValues: {
|
|
2201
|
+
'field-1': 'John Doe', // Owner
|
|
2202
|
+
'field-2': '100', // Budget
|
|
2203
|
+
'field-3': '2024-11-30', // Approval Date
|
|
2204
|
+
'field-4': 'High Priority' // Priority
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
```
|
|
2208
|
+
|
|
2209
|
+
#### 4. Dropdown Field Configuration
|
|
2210
|
+
|
|
2211
|
+
```typescript
|
|
2212
|
+
const priorityField = {
|
|
2213
|
+
id: 'field-priority',
|
|
2214
|
+
name: 'Priority',
|
|
2215
|
+
type: 'select',
|
|
2216
|
+
required: true,
|
|
2217
|
+
options: [
|
|
2218
|
+
{ label: 'Urgent', value: 'urgent' },
|
|
2219
|
+
{ label: 'Important', value: 'important' },
|
|
2220
|
+
{ label: 'Normal', value: 'normal' }
|
|
2221
|
+
]
|
|
2222
|
+
};
|
|
2223
|
+
```
|
|
2224
|
+
|
|
2225
|
+
### Field Validation
|
|
2226
|
+
|
|
2227
|
+
The component includes basic field validation rules:
|
|
2228
|
+
|
|
2229
|
+
- **Required Fields** - If field is marked as `required: true`, a value must be provided
|
|
2230
|
+
- **Number Validation** - Number fields only accept valid numeric values
|
|
2231
|
+
- **Date Validation** - Date fields only accept valid date formats
|
|
2232
|
+
- **Option Validation** - Dropdown fields only accept predefined option values
|
|
2233
|
+
|
|
2234
|
+
### API Integration
|
|
2235
|
+
|
|
2236
|
+
#### Backend Storage Format
|
|
2237
|
+
|
|
2238
|
+
Custom field values need to be stored in the backend in a specific format:
|
|
2239
|
+
|
|
2240
|
+
```typescript
|
|
2241
|
+
// Recommended format: JSON string
|
|
2242
|
+
customFieldValues: JSON.stringify({
|
|
2243
|
+
'field-1': 'John Doe',
|
|
2244
|
+
'field-2': '100'
|
|
2245
|
+
})
|
|
2246
|
+
|
|
2247
|
+
// Or array format (requires backend support)
|
|
2248
|
+
customFieldValues: [
|
|
2249
|
+
{ fieldId: 'field-1', value: 'John Doe' },
|
|
2250
|
+
{ fieldId: 'field-2', value: '100' }
|
|
2251
|
+
]
|
|
2252
|
+
```
|
|
2253
|
+
|
|
2254
|
+
#### Data Processing Example
|
|
2255
|
+
|
|
2256
|
+
```typescript
|
|
2257
|
+
// When saving task
|
|
2258
|
+
const saveTask = async (task) => {
|
|
2259
|
+
const payload = {
|
|
2260
|
+
...task,
|
|
2261
|
+
customFieldValues: JSON.stringify(task.customFieldValues)
|
|
2262
|
+
};
|
|
2263
|
+
await api.saveTask(payload);
|
|
2264
|
+
};
|
|
2265
|
+
|
|
2266
|
+
// When loading task
|
|
2267
|
+
const loadTask = async (taskId) => {
|
|
2268
|
+
const data = await api.getTask(taskId);
|
|
2269
|
+
return {
|
|
2270
|
+
...data,
|
|
2271
|
+
customFieldValues: JSON.parse(data.customFieldValues || '{}')
|
|
2272
|
+
};
|
|
2273
|
+
};
|
|
2274
|
+
```
|
|
2275
|
+
|
|
2276
|
+
### Best Practices
|
|
2277
|
+
|
|
2278
|
+
1. **Field Naming** - Use clear, concise field names for easy understanding
|
|
2279
|
+
2. **Required Settings** - Reasonably set required fields to avoid over-restriction
|
|
2280
|
+
3. **Option Management** - Provide complete option lists for dropdown fields
|
|
2281
|
+
4. **Data Validation** - Also validate fields in backend to ensure data integrity
|
|
2282
|
+
5. **Performance Optimization** - Avoid adding too many custom fields that affect performance
|
|
2283
|
+
|
|
2284
|
+
## Configuration Panels
|
|
2285
|
+
|
|
2286
|
+
The component provides two powerful configuration panels for customizing Gantt chart display and behavior.
|
|
2287
|
+
|
|
2288
|
+
### Gantt Configuration Panel
|
|
2289
|
+
|
|
2290
|
+
Access via the "Gantt Config" button in the toolbar.
|
|
2291
|
+
|
|
2292
|
+
#### Language Settings
|
|
2293
|
+
|
|
2294
|
+
- **Language Selection** - Switch between Chinese (zh-CN) and English (en-US)
|
|
2295
|
+
- **Auto-detection** - Automatically detects browser language on first load
|
|
2296
|
+
|
|
2297
|
+
#### Theme Settings
|
|
2298
|
+
|
|
2299
|
+
- **Light/Dark Mode** - Switch between light and dark themes
|
|
2300
|
+
- **Theme Persistence** - Theme preference saved to local storage
|
|
2301
|
+
|
|
2302
|
+
#### Dependency Line Styles
|
|
2303
|
+
|
|
2304
|
+
Configure task dependency line appearance:
|
|
2305
|
+
|
|
2306
|
+
```typescript
|
|
2307
|
+
{
|
|
2308
|
+
pathType: 'straight', // Connection path type: straight | curved
|
|
2309
|
+
color: '#409EFF', // Line color
|
|
2310
|
+
width: 2, // Line width (px)
|
|
2311
|
+
dashed: false, // Whether to use dashed line
|
|
2312
|
+
showArrow: true, // Whether to show arrow
|
|
2313
|
+
arrowSize: 6 // Arrow size (px)
|
|
2314
|
+
}
|
|
2315
|
+
```
|
|
2316
|
+
|
|
2317
|
+
**Path Types:**
|
|
2318
|
+
- **Straight** - Direct straight line connection
|
|
2319
|
+
- **Curved** - Smooth curved line connection
|
|
2320
|
+
|
|
2321
|
+
**Style Options:**
|
|
2322
|
+
- **Color** - Supports any valid CSS color value
|
|
2323
|
+
- **Width** - 1-5px recommended
|
|
2324
|
+
- **Dashed** - Creates dashed line effect
|
|
2325
|
+
- **Arrow** - Shows direction indicator at end point
|
|
2326
|
+
|
|
2327
|
+
### Column Configuration Panel
|
|
2328
|
+
|
|
2329
|
+
Access via the "Column Config" button in the toolbar.
|
|
2330
|
+
|
|
2331
|
+
#### Column Display Settings
|
|
2332
|
+
|
|
2333
|
+
Control which columns are visible in the task list:
|
|
2334
|
+
|
|
2335
|
+
```typescript
|
|
2336
|
+
const columns = [
|
|
2337
|
+
{ key: 'taskNo', label: 'Task Name', visible: true },
|
|
2338
|
+
{ key: 'start_date', label: 'Start Date', visible: true },
|
|
2339
|
+
{ key: 'end_date', label: 'End Date', visible: true },
|
|
2340
|
+
{ key: 'job_progress', label: 'Progress', visible: true },
|
|
2341
|
+
{ key: 'duration', label: 'Duration', visible: false }
|
|
2342
|
+
];
|
|
2343
|
+
```
|
|
2344
|
+
|
|
2345
|
+
#### Column Operations
|
|
2346
|
+
|
|
2347
|
+
- **Toggle Visibility** - Click checkbox to show/hide column
|
|
2348
|
+
- **Show All** - Display all columns at once
|
|
2349
|
+
- **Hide All** - Hide all columns at once
|
|
2350
|
+
- **Reset Default** - Restore to default column configuration
|
|
2351
|
+
|
|
2352
|
+
#### Column Types
|
|
2353
|
+
|
|
2354
|
+
| Column Key | Description | Format |
|
|
2355
|
+
|------------|-------------|--------|
|
|
2356
|
+
| taskNo | Task name | Text |
|
|
2357
|
+
| start_date | Start date | YYYY-MM-DD |
|
|
2358
|
+
| end_date | End date | YYYY-MM-DD |
|
|
2359
|
+
| job_progress | Progress percentage | 0-100% |
|
|
2360
|
+
| duration | Task duration | Number (days) |
|
|
2361
|
+
|
|
2362
|
+
### Configuration Persistence
|
|
2363
|
+
|
|
2364
|
+
All configuration settings are automatically saved to browser local storage:
|
|
2365
|
+
|
|
2366
|
+
```typescript
|
|
2367
|
+
// Storage keys
|
|
2368
|
+
const CONFIG_KEYS = {
|
|
2369
|
+
ganttConfig: 'vue3-gantt-config', // Gantt chart settings
|
|
2370
|
+
columnConfig: 'vue3-gantt-columns', // Column display settings
|
|
2371
|
+
customFields: 'vue3-gantt-fields' // Custom field definitions
|
|
2372
|
+
};
|
|
2373
|
+
```
|
|
2374
|
+
|
|
2375
|
+
**Benefits:**
|
|
2376
|
+
- Settings persist across page refreshes
|
|
2377
|
+
- Configuration shared across browser sessions
|
|
2378
|
+
- Easy to reset to defaults if needed
|
|
2379
|
+
|
|
2380
|
+
### Best Practices
|
|
2381
|
+
|
|
2382
|
+
1. **Line Visibility** - Use contrasting colors for dependency lines
|
|
2383
|
+
2. **Column Balance** - Don't show too many columns at once
|
|
2384
|
+
3. **Theme Consistency** - Match Gantt chart theme with application theme
|
|
2385
|
+
4. **Performance** - Complex line styles may impact performance with many tasks
|
|
2386
|
+
|
|
2387
|
+
## Task Dialog
|
|
2388
|
+
|
|
2389
|
+
The task dialog provides a comprehensive interface for creating and editing tasks with rich features.
|
|
2390
|
+
|
|
2391
|
+
### Dialog Features
|
|
2392
|
+
|
|
2393
|
+
- **Dual Mode** - Create new task or edit existing task
|
|
2394
|
+
- **Form Validation** - Real-time validation with error messages
|
|
2395
|
+
- **Custom Fields** - Support for dynamic custom field inputs
|
|
2396
|
+
- **Date Constraints** - Automatic date validation and adjustment
|
|
2397
|
+
- **Progress Control** - Visual progress slider with percentage display
|
|
2398
|
+
|
|
2399
|
+
### Basic Fields
|
|
2400
|
+
|
|
2401
|
+
#### Task Name
|
|
2402
|
+
|
|
2403
|
+
```typescript
|
|
2404
|
+
{
|
|
2405
|
+
taskNo: 'Project Planning', // Required, max length 200
|
|
2406
|
+
name: 'Project Planning' // Display name (optional)
|
|
2407
|
+
}
|
|
2408
|
+
```
|
|
2409
|
+
|
|
2410
|
+
- **Required** - Yes
|
|
2411
|
+
- **Max Length** - 200 characters
|
|
2412
|
+
- **Validation** - Cannot be empty
|
|
2413
|
+
|
|
2414
|
+
#### Date Range
|
|
2415
|
+
|
|
2416
|
+
```typescript
|
|
2417
|
+
{
|
|
2418
|
+
start_date: '2024-12-01', // Start date
|
|
2419
|
+
end_date: '2024-12-06' // End date
|
|
2420
|
+
}
|
|
2421
|
+
```
|
|
2422
|
+
|
|
2423
|
+
**Features:**
|
|
2424
|
+
- **Date Picker** - Built-in date picker for easy selection
|
|
2425
|
+
- **Auto-adjustment** - End date automatically adjusted if before start date
|
|
2426
|
+
- **Format** - YYYY-MM-DD
|
|
2427
|
+
- **Validation** - End date must be >= start date
|
|
2428
|
+
|
|
2429
|
+
#### Progress
|
|
2430
|
+
|
|
2431
|
+
```typescript
|
|
2432
|
+
{
|
|
2433
|
+
job_progress: '0.85' // Progress value (0-1)
|
|
2434
|
+
}
|
|
2435
|
+
```
|
|
2436
|
+
|
|
2437
|
+
**Features:**
|
|
2438
|
+
- **Slider Control** - Visual slider for easy adjustment
|
|
2439
|
+
- **Percentage Display** - Shows progress as percentage (0-100%)
|
|
2440
|
+
- **Decimal Support** - Supports decimal values (e.g., 0.5 = 50%)
|
|
2441
|
+
- **Validation** - Must be between 0 and 1
|
|
2442
|
+
|
|
2443
|
+
### Custom Fields Section
|
|
2444
|
+
|
|
2445
|
+
The dialog dynamically renders custom fields based on configuration:
|
|
2446
|
+
|
|
2447
|
+
```typescript
|
|
2448
|
+
// Example custom fields in dialog
|
|
2449
|
+
const customFields = [
|
|
2450
|
+
{
|
|
2451
|
+
id: 'field-1',
|
|
2452
|
+
name: 'Owner',
|
|
2453
|
+
type: 'text',
|
|
2454
|
+
value: 'John Doe'
|
|
2455
|
+
},
|
|
2456
|
+
{
|
|
2457
|
+
id: 'field-2',
|
|
2458
|
+
name: 'Budget',
|
|
2459
|
+
type: 'number',
|
|
2460
|
+
value: '10000'
|
|
2461
|
+
},
|
|
2462
|
+
{
|
|
2463
|
+
id: 'field-3',
|
|
2464
|
+
name: 'Priority',
|
|
2465
|
+
type: 'select',
|
|
2466
|
+
options: [
|
|
2467
|
+
{ label: 'High', value: 'high' },
|
|
2468
|
+
{ label: 'Medium', value: 'medium' },
|
|
2469
|
+
{ label: 'Low', value: 'low' }
|
|
2470
|
+
],
|
|
2471
|
+
value: 'high'
|
|
2472
|
+
}
|
|
2473
|
+
];
|
|
2474
|
+
```
|
|
2475
|
+
|
|
2476
|
+
**Field Types:**
|
|
2477
|
+
- **Text Input** - Single-line text field
|
|
2478
|
+
- **Number Input** - Numeric field with validation
|
|
2479
|
+
- **Date Picker** - Date selection field
|
|
2480
|
+
- **Dropdown** - Select from predefined options
|
|
2481
|
+
|
|
2482
|
+
### Form Validation
|
|
2483
|
+
|
|
2484
|
+
The dialog implements comprehensive validation:
|
|
2485
|
+
|
|
2486
|
+
```typescript
|
|
2487
|
+
// Validation rules
|
|
2488
|
+
const rules = {
|
|
2489
|
+
taskNo: [
|
|
2490
|
+
{ required: true, message: 'Task name is required' },
|
|
2491
|
+
{ max: 200, message: 'Task name cannot exceed 200 characters' }
|
|
2492
|
+
],
|
|
2493
|
+
start_date: [
|
|
2494
|
+
{ required: true, message: 'Start date is required' }
|
|
2495
|
+
],
|
|
2496
|
+
end_date: [
|
|
2497
|
+
{ required: true, message: 'End date is required' },
|
|
2498
|
+
{
|
|
2499
|
+
validator: (rule, value, callback) => {
|
|
2500
|
+
if (value < start_date) {
|
|
2501
|
+
callback(new Error('End date must be after start date'));
|
|
2502
|
+
} else {
|
|
2503
|
+
callback();
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
]
|
|
2508
|
+
};
|
|
2509
|
+
```
|
|
2510
|
+
|
|
2511
|
+
**Validation Types:**
|
|
2512
|
+
- **Required Fields** - Ensures mandatory fields are filled
|
|
2513
|
+
- **Format Validation** - Validates date and number formats
|
|
2514
|
+
- **Business Rules** - Enforces logical constraints (e.g., end >= start)
|
|
2515
|
+
- **Custom Field Validation** - Validates based on field type and requirements
|
|
2516
|
+
|
|
2517
|
+
### Dialog Actions
|
|
2518
|
+
|
|
2519
|
+
#### Save Button
|
|
2520
|
+
|
|
2521
|
+
- Validates all fields before saving
|
|
2522
|
+
- Shows error messages if validation fails
|
|
2523
|
+
- Emits save event with task data
|
|
2524
|
+
- Closes dialog on successful save
|
|
2525
|
+
|
|
2526
|
+
#### Cancel Button
|
|
2527
|
+
|
|
2528
|
+
- Closes dialog without saving
|
|
2529
|
+
- Discards any unsaved changes
|
|
2530
|
+
- No confirmation required
|
|
2531
|
+
|
|
2532
|
+
### Best Practices
|
|
2533
|
+
|
|
2534
|
+
1. **Clear Naming** - Use descriptive task names
|
|
2535
|
+
2. **Date Planning** - Set realistic date ranges
|
|
2536
|
+
3. **Progress Updates** - Regularly update progress values
|
|
2537
|
+
4. **Custom Fields** - Use custom fields for project-specific data
|
|
2538
|
+
5. **Validation** - Pay attention to validation messages
|
|
2539
|
+
|
|
2540
|
+
## Message Toast
|
|
2541
|
+
|
|
2542
|
+
The component includes a built-in message toast system for providing user feedback.
|
|
2543
|
+
|
|
2544
|
+
### Message Types
|
|
2545
|
+
|
|
2546
|
+
Three types of messages are supported:
|
|
2547
|
+
|
|
2548
|
+
| Type | Icon | Color | Usage |
|
|
2549
|
+
|------|------|-------|-------|
|
|
2550
|
+
| Success | ✓ | Green | Successful operations (save, delete, etc.) |
|
|
2551
|
+
| Error | ✗ | Red | Failed operations (validation errors, API errors) |
|
|
2552
|
+
| Warning | ⚠ | Orange | Warnings (unsaved changes, potential issues) |
|
|
2553
|
+
|
|
2554
|
+
### Usage
|
|
2555
|
+
|
|
2556
|
+
#### Display Success Message
|
|
2557
|
+
|
|
2558
|
+
```typescript
|
|
2559
|
+
// In component
|
|
2560
|
+
import { useMessage } from '@/composables/useMessage';
|
|
2561
|
+
|
|
2562
|
+
const { showMessage } = useMessage();
|
|
2563
|
+
|
|
2564
|
+
// Show success message
|
|
2565
|
+
showMessage('Task saved successfully', 'success');
|
|
2566
|
+
```
|
|
2567
|
+
|
|
2568
|
+
#### Display Error Message
|
|
2569
|
+
|
|
2570
|
+
```typescript
|
|
2571
|
+
// Show error message
|
|
2572
|
+
showMessage('Failed to save task: Invalid data', 'error');
|
|
2573
|
+
```
|
|
2574
|
+
|
|
2575
|
+
#### Display Warning Message
|
|
2576
|
+
|
|
2577
|
+
```typescript
|
|
2578
|
+
// Show warning message
|
|
2579
|
+
showMessage('Unsaved changes will be lost', 'warning');
|
|
2580
|
+
```
|
|
2581
|
+
|
|
2582
|
+
### Message Behavior
|
|
2583
|
+
|
|
2584
|
+
**Auto-dismissal:**
|
|
2585
|
+
- Success messages: 3 seconds
|
|
2586
|
+
- Error messages: 5 seconds
|
|
2587
|
+
- Warning messages: 4 seconds
|
|
2588
|
+
|
|
2589
|
+
**Manual Dismissal:**
|
|
2590
|
+
- Click message to dismiss immediately
|
|
2591
|
+
- Hover to pause auto-dismissal timer
|
|
2592
|
+
|
|
2593
|
+
**Positioning:**
|
|
2594
|
+
- Top-right corner of screen
|
|
2595
|
+
- Stacked vertically for multiple messages
|
|
2596
|
+
- Maximum 3 messages displayed simultaneously
|
|
2597
|
+
|
|
2598
|
+
### Message Queue
|
|
2599
|
+
|
|
2600
|
+
The toast system manages a message queue:
|
|
2601
|
+
|
|
2602
|
+
```typescript
|
|
2603
|
+
// Message queue properties
|
|
2604
|
+
interface Message {
|
|
2605
|
+
id: string; // Unique message ID
|
|
2606
|
+
type: 'success' | 'error' | 'warning';
|
|
2607
|
+
content: string; // Message text
|
|
2608
|
+
duration: number; // Display duration (ms)
|
|
2609
|
+
timestamp: number; // Creation timestamp
|
|
2610
|
+
}
|
|
2611
|
+
```
|
|
2612
|
+
|
|
2613
|
+
**Queue Management:**
|
|
2614
|
+
- New messages added to end of queue
|
|
2615
|
+
- Oldest messages dismissed first
|
|
2616
|
+
- Prevents duplicate messages
|
|
2617
|
+
|
|
2618
|
+
### Styling
|
|
2619
|
+
|
|
2620
|
+
Messages are styled according to type:
|
|
2621
|
+
|
|
2622
|
+
```css
|
|
2623
|
+
/* Success message */
|
|
2624
|
+
.message-success {
|
|
2625
|
+
background: #f0f9ff;
|
|
2626
|
+
border-left: 4px solid #67c23a;
|
|
2627
|
+
color: #67c23a;
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
/* Error message */
|
|
2631
|
+
.message-error {
|
|
2632
|
+
background: #fef0f0;
|
|
2633
|
+
border-left: 4px solid #f56c6c;
|
|
2634
|
+
color: #f56c6c;
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
/* Warning message */
|
|
2638
|
+
.message-warning {
|
|
2639
|
+
background: #fdf6ec;
|
|
2640
|
+
border-left: 4px solid #e6a23c;
|
|
2641
|
+
color: #e6a23c;
|
|
2642
|
+
}
|
|
2643
|
+
```
|
|
2644
|
+
|
|
2645
|
+
### Best Practices
|
|
2646
|
+
|
|
2647
|
+
1. **Clear Messages** - Use clear, concise message text
|
|
2648
|
+
2. **Appropriate Types** - Choose correct message type for situation
|
|
2649
|
+
3. **User Feedback** - Provide feedback for all user actions
|
|
2650
|
+
4. **Error Details** - Include helpful information in error messages
|
|
2651
|
+
5. **Avoid Spam** - Don't show too many messages in short time
|
|
2652
|
+
|
|
2653
|
+
## Delete Confirmation Dialog
|
|
2654
|
+
|
|
2655
|
+
The delete confirmation dialog ensures safe task deletion with clear warnings and options.
|
|
2656
|
+
|
|
2657
|
+
### Dialog Features
|
|
2658
|
+
|
|
2659
|
+
- **Warning Display** - Shows clear warning about deletion consequences
|
|
2660
|
+
- **Cascade Warning** - Informs about child task deletion
|
|
2661
|
+
- **Confirmation Required** - Prevents accidental deletions
|
|
2662
|
+
- **Action Buttons** - Clear confirm and cancel options
|
|
2663
|
+
|
|
2664
|
+
### Dialog Content
|
|
2665
|
+
|
|
2666
|
+
#### Warning Message
|
|
2667
|
+
|
|
2668
|
+
```
|
|
2669
|
+
⚠️ Warning: You are about to delete this task
|
|
2670
|
+
```
|
|
2671
|
+
|
|
2672
|
+
#### Cascade Warning (for parent tasks)
|
|
2673
|
+
|
|
2674
|
+
```
|
|
2675
|
+
Note: This will also delete all child tasks under this task.
|
|
2676
|
+
Are you sure you want to continue?
|
|
2677
|
+
```
|
|
2678
|
+
|
|
2679
|
+
#### Confirmation Question
|
|
2680
|
+
|
|
2681
|
+
```
|
|
2682
|
+
Are you sure you want to delete this task?
|
|
2683
|
+
```
|
|
2684
|
+
|
|
2685
|
+
### Dialog Actions
|
|
2686
|
+
|
|
2687
|
+
#### Confirm Button
|
|
2688
|
+
|
|
2689
|
+
- **Text** - "Confirm" or "Delete"
|
|
2690
|
+
- **Style** - Red/danger color to indicate destructive action
|
|
2691
|
+
- **Action** - Deletes task and all child tasks (if any)
|
|
2692
|
+
- **Feedback** - Shows success message after deletion
|
|
2693
|
+
|
|
2694
|
+
#### Cancel Button
|
|
2695
|
+
|
|
2696
|
+
- **Text** - "Cancel"
|
|
2697
|
+
- **Style** - Gray/neutral color
|
|
2698
|
+
- **Action** - Closes dialog without deleting
|
|
2699
|
+
- **Feedback** - No action taken
|
|
2700
|
+
|
|
2701
|
+
### Deletion Behavior
|
|
2702
|
+
|
|
2703
|
+
#### Simple Task Deletion
|
|
2704
|
+
|
|
2705
|
+
When deleting a task without children:
|
|
2706
|
+
|
|
2707
|
+
```typescript
|
|
2708
|
+
// Single task deletion
|
|
2709
|
+
const deleteTask = (taskId: string) => {
|
|
2710
|
+
// 1. Show confirmation dialog
|
|
2711
|
+
// 2. User confirms
|
|
2712
|
+
// 3. Delete task from data
|
|
2713
|
+
// 4. Show success message
|
|
2714
|
+
// 5. Update UI
|
|
2715
|
+
};
|
|
2716
|
+
```
|
|
2717
|
+
|
|
2718
|
+
#### Parent Task Deletion
|
|
2719
|
+
|
|
2720
|
+
When deleting a task with children:
|
|
2721
|
+
|
|
2722
|
+
```typescript
|
|
2723
|
+
// Parent task with children
|
|
2724
|
+
const deleteTaskWithChildren = (taskId: string) => {
|
|
2725
|
+
// 1. Show confirmation dialog with cascade warning
|
|
2726
|
+
// 2. User confirms
|
|
2727
|
+
// 3. Delete all child tasks recursively
|
|
2728
|
+
// 4. Delete parent task
|
|
2729
|
+
// 5. Show success message
|
|
2730
|
+
// 6. Update UI
|
|
2731
|
+
};
|
|
2732
|
+
```
|
|
2733
|
+
|
|
2734
|
+
**Cascade Deletion:**
|
|
2735
|
+
- All child tasks are deleted
|
|
2736
|
+
- Child tasks' children are also deleted
|
|
2737
|
+
- Entire subtree is removed from data
|
|
2738
|
+
|
|
2739
|
+
### Safety Features
|
|
2740
|
+
|
|
2741
|
+
#### Double Confirmation
|
|
2742
|
+
|
|
2743
|
+
For critical deletions, the dialog may require additional confirmation:
|
|
2744
|
+
|
|
2745
|
+
```typescript
|
|
2746
|
+
// Example: Delete task with many children
|
|
2747
|
+
if (childCount > 10) {
|
|
2748
|
+
// Show additional confirmation step
|
|
2749
|
+
const confirmed = await showDoubleConfirmation();
|
|
2750
|
+
if (!confirmed) return;
|
|
2751
|
+
}
|
|
2752
|
+
```
|
|
2753
|
+
|
|
2754
|
+
#### Undo Support (Optional)
|
|
2755
|
+
|
|
2756
|
+
The component can be extended to support undo:
|
|
2757
|
+
|
|
2758
|
+
```typescript
|
|
2759
|
+
// Store deleted tasks for potential undo
|
|
2760
|
+
const deletedTasks = [];
|
|
2761
|
+
|
|
2762
|
+
const deleteTask = (task) => {
|
|
2763
|
+
// Save task before deletion
|
|
2764
|
+
deletedTasks.push({
|
|
2765
|
+
task: task,
|
|
2766
|
+
timestamp: Date.now()
|
|
2767
|
+
});
|
|
2768
|
+
|
|
2769
|
+
// Perform deletion
|
|
2770
|
+
performDeletion(task.id);
|
|
2771
|
+
};
|
|
2772
|
+
|
|
2773
|
+
const undoDelete = () => {
|
|
2774
|
+
const lastDeleted = deletedTasks.pop();
|
|
2775
|
+
if (lastDeleted) {
|
|
2776
|
+
restoreTask(lastDeleted.task);
|
|
2777
|
+
}
|
|
2778
|
+
};
|
|
2779
|
+
```
|
|
2780
|
+
|
|
2781
|
+
### Best Practices
|
|
2782
|
+
|
|
2783
|
+
1. **Clear Warnings** - Always show clear warnings before deletion
|
|
2784
|
+
2. **Cascade Info** - Inform users about child task deletion
|
|
2785
|
+
3. **Confirmation** - Always require confirmation for deletion
|
|
2786
|
+
4. **Feedback** - Show success message after deletion
|
|
2787
|
+
5. **Recovery** - Consider implementing undo functionality
|
|
2788
|
+
|
|
2789
|
+
## Tree Task Structure
|
|
2790
|
+
|
|
2791
|
+
The component supports hierarchical task tree structure with rich visualization and interaction features.
|
|
2792
|
+
|
|
2793
|
+
### Core Features
|
|
2794
|
+
|
|
2795
|
+
- **Multi-level Hierarchy** - Support unlimited task nesting levels
|
|
2796
|
+
- **Visual Indentation** - Clear visual representation of task hierarchy
|
|
2797
|
+
- **Connection Lines** - Tree-style connection lines between parent and child tasks
|
|
2798
|
+
- **Expand/Collapse** - Interactive expand/collapse for parent tasks
|
|
2799
|
+
- **Task Numbering** - Hierarchical task numbering (1, 1.1, 1.1.1, etc.)
|
|
2800
|
+
- **Inline Operations** - Add/delete child tasks directly from task row
|
|
2801
|
+
|
|
2802
|
+
### Task Hierarchy Structure
|
|
2803
|
+
|
|
2804
|
+
Tasks can be organized in a tree structure:
|
|
2805
|
+
|
|
2806
|
+
```typescript
|
|
2807
|
+
// Example task hierarchy
|
|
2808
|
+
const tasks = [
|
|
2809
|
+
{
|
|
2810
|
+
id: '1',
|
|
2811
|
+
taskNo: 'Project Phase 1',
|
|
2812
|
+
level: 0, // Root level
|
|
2813
|
+
children: [
|
|
2814
|
+
{
|
|
2815
|
+
id: '1-1',
|
|
2816
|
+
taskNo: 'Task 1.1',
|
|
2817
|
+
level: 1, // First level child
|
|
2818
|
+
children: [
|
|
2819
|
+
{
|
|
2820
|
+
id: '1-1-1',
|
|
2821
|
+
taskNo: 'Task 1.1.1',
|
|
2822
|
+
level: 2 // Second level child
|
|
2823
|
+
}
|
|
2824
|
+
]
|
|
2825
|
+
},
|
|
2826
|
+
{
|
|
2827
|
+
id: '1-2',
|
|
2828
|
+
taskNo: 'Task 1.2',
|
|
2829
|
+
level: 1
|
|
2830
|
+
}
|
|
2831
|
+
]
|
|
2832
|
+
}
|
|
2833
|
+
];
|
|
2834
|
+
```
|
|
2835
|
+
|
|
2836
|
+
**Level Properties:**
|
|
2837
|
+
- `level: 0` - Root task (no parent)
|
|
2838
|
+
- `level: 1` - First level child
|
|
2839
|
+
- `level: 2` - Second level child
|
|
2840
|
+
- And so on...
|
|
2841
|
+
|
|
2842
|
+
### Visual Elements
|
|
2843
|
+
|
|
2844
|
+
#### Indentation
|
|
2845
|
+
|
|
2846
|
+
Each level of hierarchy is indented by a fixed amount:
|
|
2847
|
+
|
|
2848
|
+
```css
|
|
2849
|
+
/* Indentation per level */
|
|
2850
|
+
.task-row {
|
|
2851
|
+
padding-left: calc(level * 24px);
|
|
2852
|
+
}
|
|
2853
|
+
```
|
|
2854
|
+
|
|
2855
|
+
**Visual Effect:**
|
|
2856
|
+
- Level 0: No indentation
|
|
2857
|
+
- Level 1: 24px indentation
|
|
2858
|
+
- Level 2: 48px indentation
|
|
2859
|
+
- Level 3: 72px indentation
|
|
2860
|
+
|
|
2861
|
+
#### Connection Lines
|
|
2862
|
+
|
|
2863
|
+
Tree-style connection lines show parent-child relationships:
|
|
2864
|
+
|
|
2865
|
+
```
|
|
2866
|
+
├─ Task 1.0 (parent)
|
|
2867
|
+
│ ├─ Task 1.1 (child)
|
|
2868
|
+
│ │ ├─ Task 1.1.1 (grandchild)
|
|
2869
|
+
│ │ └─ Task 1.1.2 (grandchild)
|
|
2870
|
+
│ └─ Task 1.2 (child)
|
|
2871
|
+
└─ Task 2.0 (parent)
|
|
2872
|
+
```
|
|
2873
|
+
|
|
2874
|
+
**Line Types:**
|
|
2875
|
+
- **Vertical Line** - Connects parent to children
|
|
2876
|
+
- **Horizontal Line** - Connects to task name
|
|
2877
|
+
- **Corner** - Smooth corner at connection point
|
|
2878
|
+
|
|
2879
|
+
#### Expand/Collapse Icons
|
|
2880
|
+
|
|
2881
|
+
Parent tasks display expand/collapse indicators:
|
|
2882
|
+
|
|
2883
|
+
- **Expanded (▾)** - Shows children, click to collapse
|
|
2884
|
+
- **Collapsed (▸)** - Hides children, click to expand
|
|
2885
|
+
- **Leaf Task** - No icon (no children)
|
|
2886
|
+
|
|
2887
|
+
### Interaction Operations
|
|
2888
|
+
|
|
2889
|
+
#### Expand/Collapse Tasks
|
|
2890
|
+
|
|
2891
|
+
Click the expand/collapse icon to toggle visibility:
|
|
2892
|
+
|
|
2893
|
+
```typescript
|
|
2894
|
+
// Expand task
|
|
2895
|
+
const expandTask = (taskId: string) => {
|
|
2896
|
+
const task = findTask(taskId);
|
|
2897
|
+
if (task) {
|
|
2898
|
+
task.expanded = true;
|
|
2899
|
+
// Show all child tasks
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
|
|
2903
|
+
// Collapse task
|
|
2904
|
+
const collapseTask = (taskId: string) => {
|
|
2905
|
+
const task = findTask(taskId);
|
|
2906
|
+
if (task) {
|
|
2907
|
+
task.expanded = false;
|
|
2908
|
+
// Hide all child tasks
|
|
2909
|
+
}
|
|
2910
|
+
};
|
|
2911
|
+
```
|
|
2912
|
+
|
|
2913
|
+
**Keyboard Support:**
|
|
2914
|
+
- `Right Arrow` - Expand task
|
|
2915
|
+
- `Left Arrow` - Collapse task
|
|
2916
|
+
|
|
2917
|
+
#### Add Child Task
|
|
2918
|
+
|
|
2919
|
+
Click the "+" button on a task row to add a child:
|
|
2920
|
+
|
|
2921
|
+
```typescript
|
|
2922
|
+
const addChildTask = (parentTaskId: string) => {
|
|
2923
|
+
const parentTask = findTask(parentTaskId);
|
|
2924
|
+
if (parentTask) {
|
|
2925
|
+
const newTask = {
|
|
2926
|
+
id: generateId(),
|
|
2927
|
+
taskNo: 'New Task',
|
|
2928
|
+
level: parentTask.level + 1,
|
|
2929
|
+
parentId: parentTaskId
|
|
2930
|
+
};
|
|
2931
|
+
parentTask.children.push(newTask);
|
|
2932
|
+
// Auto-expand parent to show new child
|
|
2933
|
+
parentTask.expanded = true;
|
|
2934
|
+
}
|
|
2935
|
+
};
|
|
2936
|
+
```
|
|
2937
|
+
|
|
2938
|
+
#### Delete Task
|
|
2939
|
+
|
|
2940
|
+
Click the "×" button to delete a task:
|
|
2941
|
+
|
|
2942
|
+
```typescript
|
|
2943
|
+
const deleteTask = (taskId: string) => {
|
|
2944
|
+
// Show confirmation dialog
|
|
2945
|
+
const confirmed = showDeleteConfirmation(taskId);
|
|
2946
|
+
if (confirmed) {
|
|
2947
|
+
// Delete task and all children
|
|
2948
|
+
removeTaskAndChildren(taskId);
|
|
2949
|
+
}
|
|
2950
|
+
};
|
|
2951
|
+
```
|
|
2952
|
+
|
|
2953
|
+
**Cascade Deletion:**
|
|
2954
|
+
- Deleting a parent task deletes all its children
|
|
2955
|
+
- Deleting a child task only deletes that child
|
|
2956
|
+
- Confirmation dialog warns about cascade deletion
|
|
2957
|
+
|
|
2958
|
+
### Parent-Child Task Linkage
|
|
2959
|
+
|
|
2960
|
+
#### Date Constraints
|
|
2961
|
+
|
|
2962
|
+
Child task dates are constrained by parent task dates:
|
|
2963
|
+
|
|
2964
|
+
```typescript
|
|
2965
|
+
// Child task cannot extend beyond parent
|
|
2966
|
+
const validateChildDates = (child: Task, parent: Task) => {
|
|
2967
|
+
if (child.start_date < parent.start_date) {
|
|
2968
|
+
child.start_date = parent.start_date;
|
|
2969
|
+
}
|
|
2970
|
+
if (child.end_date > parent.end_date) {
|
|
2971
|
+
child.end_date = parent.end_date;
|
|
2972
|
+
}
|
|
2973
|
+
};
|
|
2974
|
+
```
|
|
2975
|
+
|
|
2976
|
+
**Rules:**
|
|
2977
|
+
- Child start date >= Parent start date
|
|
2978
|
+
- Child end date <= Parent end date
|
|
2979
|
+
- Parent dates automatically adjust if needed
|
|
2980
|
+
|
|
2981
|
+
#### Progress Calculation
|
|
2982
|
+
|
|
2983
|
+
Parent task progress is calculated from children:
|
|
2984
|
+
|
|
2985
|
+
```typescript
|
|
2986
|
+
// Calculate parent progress from children
|
|
2987
|
+
const calculateParentProgress = (parent: Task) => {
|
|
2988
|
+
if (!parent.children || parent.children.length === 0) {
|
|
2989
|
+
return parent.job_progress;
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2992
|
+
const totalProgress = parent.children.reduce((sum, child) => {
|
|
2993
|
+
return sum + parseFloat(child.job_progress);
|
|
2994
|
+
}, 0);
|
|
2995
|
+
|
|
2996
|
+
return (totalProgress / parent.children.length).toFixed(2);
|
|
2997
|
+
};
|
|
2998
|
+
```
|
|
2999
|
+
|
|
3000
|
+
**Calculation Method:**
|
|
3001
|
+
- Average of all child task progress
|
|
3002
|
+
- Automatically updates when child progress changes
|
|
3003
|
+
- Can be overridden manually
|
|
3004
|
+
|
|
3005
|
+
### Style Customization
|
|
3006
|
+
|
|
3007
|
+
#### Indentation Width
|
|
3008
|
+
|
|
3009
|
+
Customize indentation per level:
|
|
3010
|
+
|
|
3011
|
+
```typescript
|
|
3012
|
+
const config = {
|
|
3013
|
+
indentationWidth: 24 // px per level
|
|
3014
|
+
};
|
|
3015
|
+
```
|
|
3016
|
+
|
|
3017
|
+
#### Line Styles
|
|
3018
|
+
|
|
3019
|
+
Customize connection line appearance:
|
|
3020
|
+
|
|
3021
|
+
```css
|
|
3022
|
+
.tree-line {
|
|
3023
|
+
color: #dcdfe6; /* Line color */
|
|
3024
|
+
width: 1px; /* Line width */
|
|
3025
|
+
style: solid; /* Line style */
|
|
3026
|
+
}
|
|
3027
|
+
```
|
|
3028
|
+
|
|
3029
|
+
#### Icon Styles
|
|
3030
|
+
|
|
3031
|
+
Customize expand/collapse icons:
|
|
3032
|
+
|
|
3033
|
+
```css
|
|
3034
|
+
.expand-icon {
|
|
3035
|
+
color: #909399; /* Icon color */
|
|
3036
|
+
font-size: 14px; /* Icon size */
|
|
3037
|
+
cursor: pointer; /* Pointer cursor */
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
.expand-icon:hover {
|
|
3041
|
+
color: #409EFF; /* Hover color */
|
|
3042
|
+
}
|
|
3043
|
+
```
|
|
3044
|
+
|
|
3045
|
+
### Best Practices
|
|
3046
|
+
|
|
3047
|
+
1. **Shallow Hierarchy** - Keep hierarchy depth reasonable (3-5 levels max)
|
|
3048
|
+
2. **Clear Naming** - Use descriptive names at each level
|
|
3049
|
+
3. **Logical Grouping** - Group related tasks under same parent
|
|
3050
|
+
4. **Regular Review** - Periodically review and reorganize structure
|
|
3051
|
+
5. **Consistent Indentation** - Maintain consistent indentation for clarity
|
|
3052
|
+
|
|
3053
|
+
## Internationalization Support
|
|
3054
|
+
|
|
3055
|
+
### Supported Languages
|
|
3056
|
+
|
|
3057
|
+
| Language | Code | Status |
|
|
3058
|
+
|----------|------|--------|
|
|
3059
|
+
| 🇨🇳 Simplified Chinese | zh-CN | ✅ Full support |
|
|
3060
|
+
| 🇺🇸 English | en-US | ✅ Full support |
|
|
3061
|
+
| 🇯🇵 Japanese | ja-JP | ✅ Full support |
|
|
3062
|
+
| 🇰🇷 Korean | ko-KR | ✅ Full support |
|
|
3063
|
+
| 🇫🇷 French | fr-FR | ✅ Full support |
|
|
3064
|
+
| 🇩🇪 German | de-DE | ✅ Full support |
|
|
3065
|
+
| 🇪🇸 Spanish | es-ES | ✅ Full support |
|
|
3066
|
+
| 🇷🇺 Russian | ru-RU | ✅ Full support |
|
|
3067
|
+
|
|
3068
|
+
### Usage
|
|
3069
|
+
|
|
3070
|
+
#### 1. Switch Language
|
|
3071
|
+
|
|
3072
|
+
In the top right corner of the Gantt chart toolbar, click the language selector to switch the interface language:
|
|
3073
|
+
|
|
3074
|
+
```typescript
|
|
3075
|
+
import { setLocale } from './components/gantt/i18n';
|
|
3076
|
+
|
|
3077
|
+
// Switch to English
|
|
3078
|
+
setLocale('en-US');
|
|
3079
|
+
|
|
3080
|
+
// Switch to Chinese
|
|
3081
|
+
setLocale('zh-CN');
|
|
3082
|
+
```
|
|
3083
|
+
|
|
3084
|
+
#### 2. Get Current Language
|
|
3085
|
+
|
|
3086
|
+
```typescript
|
|
3087
|
+
import { getLocale } from './components/gantt/i18n';
|
|
3088
|
+
|
|
3089
|
+
const currentLang = getLocale(); // 'zh-CN' or 'en-US'
|
|
3090
|
+
```
|
|
3091
|
+
|
|
3092
|
+
#### 3. Use Translation in Components
|
|
3093
|
+
|
|
3094
|
+
```vue
|
|
3095
|
+
<script setup lang="ts">
|
|
3096
|
+
import { useI18n } from './components/gantt/i18n';
|
|
3097
|
+
|
|
3098
|
+
const { t, locale } = useI18n();
|
|
3099
|
+
</script>
|
|
3100
|
+
|
|
3101
|
+
<template>
|
|
3102
|
+
<div>
|
|
3103
|
+
<h1>{{ t('common.title') }}</h1>
|
|
3104
|
+
<button>{{ t('common.confirm') }}</button>
|
|
3105
|
+
<p>{{ t('task.name') }}</p>
|
|
3106
|
+
</div>
|
|
3107
|
+
</template>
|
|
3108
|
+
```
|
|
3109
|
+
|
|
3110
|
+
### i18n Features
|
|
3111
|
+
|
|
3112
|
+
- ✅ **Instant Switching** - No page refresh required to switch languages
|
|
3113
|
+
- ✅ **Auto Save** - Language selection automatically saved to browser localStorage
|
|
3114
|
+
- ✅ **Complete Coverage** - All interface text has been translated
|
|
3115
|
+
- ✅ **Dynamic Headers** - Timeline headers (months, weekdays, etc.) automatically formatted based on language
|
|
3116
|
+
- ✅ **Type Safe** - TypeScript provides complete type support
|
|
3117
|
+
- ✅ **Easy Extension** - Can easily add new language support
|
|
3118
|
+
|
|
3119
|
+
### Translated Interface Elements
|
|
3120
|
+
|
|
3121
|
+
#### Toolbar
|
|
3122
|
+
- Date picker separator ("to" / "至")
|
|
3123
|
+
- View mode buttons (Month/Week/Day/Hour)
|
|
3124
|
+
- Link legend title and all link types
|
|
3125
|
+
|
|
3126
|
+
#### Task Headers
|
|
3127
|
+
- No. (序号)
|
|
3128
|
+
- Task Name (任务名称)
|
|
3129
|
+
- Priority (优先级)
|
|
3130
|
+
- Start Date (开始时间)
|
|
3131
|
+
- End Date (结束时间)
|
|
3132
|
+
- Duration (耗时)
|
|
3133
|
+
- Progress (进度)
|
|
3134
|
+
|
|
3135
|
+
#### Timeline Headers
|
|
3136
|
+
- Month names (January/一月, February/二月...)
|
|
3137
|
+
- Weekday names (Monday/星期一, Tuesday/星期二...)
|
|
3138
|
+
- Date format (01/01日, 02/02日...)
|
|
3139
|
+
- Hour format (0:00/0点, 1:00/1点...)
|
|
3140
|
+
- Week title (Week 1/第1周)
|
|
3141
|
+
|
|
3142
|
+
#### Configuration Panel
|
|
3143
|
+
- Gantt configuration title
|
|
3144
|
+
- Theme settings options
|
|
3145
|
+
- All link configuration options
|
|
3146
|
+
- All buttons and labels
|
|
3147
|
+
|
|
3148
|
+
### Adding New Languages
|
|
3149
|
+
|
|
3150
|
+
To add new language support, follow these steps:
|
|
3151
|
+
|
|
3152
|
+
1. Create a new language file in the `src/components/gantt/i18n/locales/` directory (e.g., `ja-JP.ts`)
|
|
3153
|
+
2. Copy the structure from `zh-CN.ts` or `en-US.ts`
|
|
3154
|
+
3. Translate all text
|
|
3155
|
+
4. Import and register the new language in `src/components/gantt/i18n/index.ts`:
|
|
3156
|
+
|
|
3157
|
+
```typescript
|
|
3158
|
+
import jaJP from './locales/ja-JP';
|
|
3159
|
+
import koKR from './locales/ko-KR';
|
|
3160
|
+
import frFR from './locales/fr-FR';
|
|
3161
|
+
import deDE from './locales/de-DE';
|
|
3162
|
+
import esES from './locales/es-ES';
|
|
3163
|
+
import ruRU from './locales/ru-RU';
|
|
3164
|
+
|
|
3165
|
+
const messages: Record<Locale, Messages> = {
|
|
3166
|
+
'zh-CN': zhCN,
|
|
3167
|
+
'en-US': enUS,
|
|
3168
|
+
'ja-JP': jaJP, // Added Japanese
|
|
3169
|
+
'ko-KR': koKR, // Added Korean
|
|
3170
|
+
'fr-FR': frFR, // Added French
|
|
3171
|
+
'de-DE': deDE, // Added German
|
|
3172
|
+
'es-ES': esES, // Added Spanish
|
|
3173
|
+
'ru-RU': ruRU // Added Russian
|
|
3174
|
+
};
|
|
3175
|
+
```
|
|
3176
|
+
|
|
3177
|
+
5. Update the `getLocales()` function to add new language options
|
|
3178
|
+
|
|
3179
|
+
### Language Pack Structure
|
|
3180
|
+
|
|
3181
|
+
```typescript
|
|
3182
|
+
export default {
|
|
3183
|
+
common: { // Common text
|
|
3184
|
+
confirm: 'Confirm',
|
|
3185
|
+
cancel: 'Cancel',
|
|
3186
|
+
// ...
|
|
3187
|
+
},
|
|
3188
|
+
date: { // Date and time
|
|
3189
|
+
year: 'Year',
|
|
3190
|
+
month: 'Month',
|
|
3191
|
+
// ...
|
|
3192
|
+
},
|
|
3193
|
+
viewMode: { // View mode
|
|
3194
|
+
month: 'Month',
|
|
3195
|
+
week: 'Week',
|
|
3196
|
+
// ...
|
|
3197
|
+
},
|
|
3198
|
+
task: { // Task related
|
|
3199
|
+
name: 'Task Name',
|
|
3200
|
+
priority: 'Priority',
|
|
3201
|
+
// ...
|
|
3202
|
+
},
|
|
3203
|
+
// More categories...
|
|
3204
|
+
}
|
|
3205
|
+
```
|
|
3206
|
+
|
|
3207
|
+
|
|
3208
|
+
## Interactive Features
|
|
3209
|
+
|
|
3210
|
+
| Operation | Description | Effect |
|
|
3211
|
+
|-----------|-------------|--------|
|
|
3212
|
+
| 🖱️ **Drag & Move** | Drag entire task bar | Modify task start and end dates |
|
|
3213
|
+
| 📏 **Resize** | Drag task bar left/right edges | Adjust task duration |
|
|
3214
|
+
| 📊 **Progress Adjust** | Drag triangle slider at bottom of task bar | Adjust task completion progress |
|
|
3215
|
+
|
|
3216
|
+
### Task Bar Operations
|
|
3217
|
+
|
|
3218
|
+
- **Drag & Move** - Drag task bar to modify start and end dates
|
|
3219
|
+
- **Resize** - Drag task bar left/right edges to adjust duration
|
|
3220
|
+
- **Progress Adjust** - Drag triangle slider at bottom to adjust progress
|
|
3221
|
+
|
|
3222
|
+
### Parent-Child Task Linkage
|
|
3223
|
+
|
|
3224
|
+
- Moving parent tasks causes child tasks to move along
|
|
3225
|
+
- Resizing parent tasks checks child task constraints
|
|
3226
|
+
- Child tasks cannot start before parent tasks
|
|
3227
|
+
|
|
3228
|
+
### Quick Operations
|
|
3229
|
+
|
|
3230
|
+
- Click the **+** button in the top left to add root tasks
|
|
3231
|
+
- Click the calendar icon to jump to today
|
|
3232
|
+
- Right-click task rows to add subtasks, edit, or delete
|
|
3233
|
+
|
|
3234
|
+
## Link Configuration
|
|
3235
|
+
|
|
3236
|
+
### Link Styles
|
|
3237
|
+
|
|
3238
|
+
```typescript
|
|
3239
|
+
interface LinkConfig {
|
|
3240
|
+
color: string; // Link color
|
|
3241
|
+
width: number; // Link width
|
|
3242
|
+
dashArray?: string; // Dash style
|
|
3243
|
+
showArrow: boolean; // Show arrow
|
|
3244
|
+
arrowSize: number; // Arrow size
|
|
3245
|
+
showLabels: boolean; // Show labels
|
|
3246
|
+
pathType: LinkPathType; // Path type
|
|
3247
|
+
cornerRadius: number; // Corner radius
|
|
3248
|
+
smoothCorners: boolean; // Smooth corners
|
|
3249
|
+
}
|
|
3250
|
+
```
|
|
3251
|
+
|
|
3252
|
+
### Path Types
|
|
3253
|
+
|
|
3254
|
+
```
|
|
3255
|
+
Straight Bezier Curve Right Angle
|
|
3256
|
+
┌─────┐ ┌─────┐ ┌─────┐
|
|
3257
|
+
│Task A│ ────────▶│Task A│ ╭───────▶ │Task A│ ┐
|
|
3258
|
+
└─────┘ └─────┘ ╰─┐ └─────┘ │
|
|
3259
|
+
│ │
|
|
3260
|
+
┌─────┐ ┌─────┐
|
|
3261
|
+
│Task B│ │Task B│
|
|
3262
|
+
└─────┘ └─────┘
|
|
3263
|
+
```
|
|
3264
|
+
|
|
3265
|
+
| Type | Enum | Description |
|
|
3266
|
+
|------|------|-------------|
|
|
3267
|
+
| Straight | STRAIGHT | Direct connection |
|
|
3268
|
+
| Bezier Curve | BEZIER | Smooth curve |
|
|
3269
|
+
| Right Angle | RIGHT_ANGLE | Right-angle connection |
|
|
3270
|
+
|
|
3271
|
+
## Performance Optimization
|
|
3272
|
+
|
|
3273
|
+
The component includes multiple performance optimizations:
|
|
3274
|
+
|
|
3275
|
+
- **Virtual Scrolling** - Only render tasks in the visible area
|
|
3276
|
+
- **Throttled Updates** - Use throttling to avoid frequent re-renders when data changes
|
|
3277
|
+
- **Cached Calculations** - Use computed to cache complex calculation results
|
|
3278
|
+
- **On-Demand Rendering** - Calculate and render elements like links on demand
|
|
3279
|
+
|
|
3280
|
+
## Project Structure
|
|
3281
|
+
|
|
3282
|
+
```
|
|
3283
|
+
src/
|
|
3284
|
+
├── components/
|
|
3285
|
+
│ ├── CustomFieldsDialog.vue # Custom fields dialog
|
|
3286
|
+
│ ├── DeleteConfirmDialog.vue # Delete confirmation dialog
|
|
3287
|
+
│ ├── MessageToast.vue # Message toast component
|
|
3288
|
+
│ ├── TaskDialog.vue # Task editing dialog
|
|
3289
|
+
│ └── gantt/
|
|
3290
|
+
│ ├── composables/ # Gantt composables
|
|
3291
|
+
│ │ ├── LinkConfig.ts
|
|
3292
|
+
│ │ ├── PerformanceConfig.ts
|
|
3293
|
+
│ │ ├── useHorizontalVirtualScroll.ts
|
|
3294
|
+
│ │ └── useVirtualScroll.ts
|
|
3295
|
+
│ ├── config/ # Configuration panel components
|
|
3296
|
+
│ │ ├── CheckboxConfig.vue
|
|
3297
|
+
│ │ ├── ColorInput.vue
|
|
3298
|
+
│ │ ├── ColumnConfigPanel.vue
|
|
3299
|
+
│ │ ├── ConfigSection.vue
|
|
3300
|
+
│ │ ├── DatePicker.vue
|
|
3301
|
+
│ │ ├── GanttConfigPanel.vue
|
|
3302
|
+
│ │ ├── GanttThemeSelector.vue
|
|
3303
|
+
│ │ ├── LanguageSelector.vue
|
|
3304
|
+
│ │ ├── LinkConfigPanel.vue
|
|
3305
|
+
│ │ ├── LinkTypeColorConfig.vue
|
|
3306
|
+
│ │ ├── PathTypeSelector.vue
|
|
3307
|
+
│ │ ├── SliderInput.vue
|
|
3308
|
+
│ │ └── ThemeSelector.vue
|
|
3309
|
+
│ ├── core/ # Core components
|
|
3310
|
+
│ │ ├── Gantt.vue # Main component
|
|
3311
|
+
│ │ └── SplitPane.vue # Split panel
|
|
3312
|
+
│ ├── gantt.css # Gantt styles
|
|
3313
|
+
│ ├── i18n/ # Internationalization system
|
|
3314
|
+
│ │ ├── index.ts # i18n core
|
|
3315
|
+
│ │ └── locales/ # Language packs
|
|
3316
|
+
│ │ ├── zh-CN.ts # Chinese language pack
|
|
3317
|
+
│ │ ├── zh-TW.ts # Traditional Chinese language pack
|
|
3318
|
+
│ │ ├── en-US.ts # English language pack
|
|
3319
|
+
│ │ ├── ja-JP.ts # Japanese language pack
|
|
3320
|
+
│ │ ├── ko-KR.ts # Korean language pack
|
|
3321
|
+
│ │ ├── fr-FR.ts # French language pack
|
|
3322
|
+
│ │ ├── de-DE.ts # German language pack
|
|
3323
|
+
│ │ ├── es-ES.ts # Spanish language pack
|
|
3324
|
+
│ │ └── ru-RU.ts # Russian language pack
|
|
3325
|
+
│ ├── links/ # Link components
|
|
3326
|
+
│ │ └── TaskLinks.vue # Task links
|
|
3327
|
+
│ ├── state/ # State management
|
|
3328
|
+
│ │ ├── ShareState.ts # Shared state
|
|
3329
|
+
│ │ ├── Store.ts # State store
|
|
3330
|
+
│ │ └── Symbols.ts # Injection symbols
|
|
3331
|
+
│ ├── task/ # Task-related components
|
|
3332
|
+
│ │ ├── TaskTable.vue # Task table
|
|
3333
|
+
│ │ ├── TaskHeader.vue # Task header
|
|
3334
|
+
│ │ ├── TaskContent.vue # Task content
|
|
3335
|
+
│ │ ├── TaskRow.vue # Task row
|
|
3336
|
+
│ │ └── TaskRecursionRow.vue # Recursive task row
|
|
3337
|
+
│ ├── themes/ # Theme configuration
|
|
3338
|
+
│ │ ├── GanttThemes.ts # Theme definitions
|
|
3339
|
+
│ │ └── LiquidGlass.css # Liquid glass theme
|
|
3340
|
+
│ ├── timeline/ # Timeline components
|
|
3341
|
+
│ │ ├── Bar.vue # Task bar
|
|
3342
|
+
│ │ ├── BarRecursionRow.vue # Recursive task bar
|
|
3343
|
+
│ │ ├── Milestone.vue # Milestone
|
|
3344
|
+
│ │ ├── RightTable.vue # Right Gantt chart area
|
|
3345
|
+
│ │ ├── TableContent.vue # Table content
|
|
3346
|
+
│ │ ├── TimelineHeader.vue # Timeline header
|
|
3347
|
+
│ │ ├── composables/ # Timeline composables
|
|
3348
|
+
│ │ │ ├── useBarGeometry.ts
|
|
3349
|
+
│ │ │ ├── useBarTheme.ts
|
|
3350
|
+
│ │ │ ├── useHover.ts
|
|
3351
|
+
│ │ │ ├── useInteractions.ts
|
|
3352
|
+
│ │ │ └── useProgress.ts
|
|
3353
|
+
│ │ └── utils/ # Utility functions
|
|
3354
|
+
│ │ └── dateCalc.ts
|
|
3355
|
+
│ └── types/ # Type definitions
|
|
3356
|
+
│ ├── Types.ts # Gantt types
|
|
3357
|
+
│ └── ZodSchema.ts # Data validation
|
|
3358
|
+
├── composables/ # Global composables
|
|
3359
|
+
│ ├── useCustomFields.ts # Custom fields
|
|
3360
|
+
│ ├── useMessage.ts # Message toast
|
|
3361
|
+
│ └── useTaskManagement.ts # Task management
|
|
3362
|
+
├── mock/ # Mock data
|
|
3363
|
+
│ └── mockData.ts # Sample data
|
|
3364
|
+
├── services/ # Service layer
|
|
3365
|
+
│ └── taskApi.ts # Task API
|
|
3366
|
+
├── styles/ # Global styles
|
|
3367
|
+
│ └── dialog-common.css # Dialog common styles
|
|
3368
|
+
├── types/ # Type definitions
|
|
3369
|
+
│ └── task.ts # Task types
|
|
3370
|
+
├── App.vue # Example application
|
|
3371
|
+
├── index.ts # Export entry
|
|
3372
|
+
├── main.ts # Application entry
|
|
3373
|
+
├── style.css # Global styles
|
|
3374
|
+
└── vite-env.d.ts # Vite environment types
|
|
3375
|
+
```
|
|
3376
|
+
|
|
3377
|
+
## Complete Example
|
|
3378
|
+
|
|
3379
|
+
Refer to `src/App.vue` for a complete usage example, including:
|
|
3380
|
+
|
|
3381
|
+
- Multi-level task structure
|
|
3382
|
+
- Various dependency configurations
|
|
3383
|
+
- Custom color mapping
|
|
3384
|
+
- Event handling
|
|
3385
|
+
- Internationalization integration
|
|
3386
|
+
|
|
3387
|
+
## Browser Support
|
|
3388
|
+
|
|
3389
|
+
- Chrome (Recommended)
|
|
3390
|
+
- Firefox
|
|
3391
|
+
- Safari
|
|
3392
|
+
- Edge
|
|
875
3393
|
|
|
876
3394
|
## License
|
|
877
3395
|
|