@lee576/vue3-gantt 1.0.0
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/LICENSE +21 -0
- package/README.en-US.md +647 -0
- package/README.md +730 -0
- package/dist/index.d.ts +1 -0
- package/dist/vue3-gantt.css +1 -0
- package/dist/vue3-gantt.es.js +7275 -0
- package/dist/vue3-gantt.es.js.map +1 -0
- package/dist/vue3-gantt.umd.js +123 -0
- package/dist/vue3-gantt.umd.js.map +1 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 WangLi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en-US.md
ADDED
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
# Vue3 Gantt Chart Component
|
|
2
|
+
|
|
3
|
+
**Languages:** [English](README.en-US.md) | [简体中文](README.md)
|
|
4
|
+
|
|
5
|
+
A feature-rich, highly customizable Vue 3 Gantt chart component that supports task management, dependency relationships, multiple view modes, and theme switching.
|
|
6
|
+
|
|
7
|
+
<div align="center">
|
|
8
|
+
<img src="https://img.shields.io/badge/Vue-3.5.13-4FC08D?style=for-the-badge&logo=vue.js&logoColor=white" alt="Vue 3">
|
|
9
|
+
<img src="https://img.shields.io/badge/TypeScript-5.7.2-3178C6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript">
|
|
10
|
+
<img src="https://img.shields.io/badge/Vite-6.2.0-646CFF?style=for-the-badge&logo=vite&logoColor=white" alt="Vite">
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
## Interface Preview
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
17
|
+
│ Vue3 Gantt Professional Component │
|
|
18
|
+
├─────────────────┬───────────────────────────────────────────────────────────┤
|
|
19
|
+
│ Task Name │ 12/01 12/02 12/03 12/04 12/05 12/06 12/07 12/08 │
|
|
20
|
+
├─────────────────┼───────────────────────────────────────────────────────────┤
|
|
21
|
+
│ Main Task 1 - Planning│ ████████████████████████████████████████████ 85% │
|
|
22
|
+
│ Subtask 1.1 - Requirements│ ████████████ 100% │
|
|
23
|
+
│ Main Task 2 - Development│ ████████████████████████████ 60% │
|
|
24
|
+
│ Main Task 3 - Testing│ ████████████████ 45% │
|
|
25
|
+
│ Main Task 4 - Deployment│ ████████ 30% │
|
|
26
|
+
│ Main Task 5 - Maintenance│ ████ 0% │
|
|
27
|
+
└─────────────────┴───────────────────────────────────────────────────────────┘
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Key Features:**
|
|
31
|
+
- 🎯 Left task list + Right Gantt chart timeline
|
|
32
|
+
- 📊 Visual progress bars showing task completion
|
|
33
|
+
- 🔗 Task dependency relationship lines
|
|
34
|
+
- 🎨 Multi-theme support (Light/Dark/Colorful, etc.)
|
|
35
|
+
- 🖱️ Drag to adjust task time and progress
|
|
36
|
+
- 🌍 Multi-language support (Chinese/English/Japanese/Korean/French/German/Spanish/Russian)
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **Multiple View Modes** - Month, Day, Week, and Hour time granularity views
|
|
41
|
+
- **Task Dependencies** - Support for FS, SS, FF, SF dependency types
|
|
42
|
+
- **Theme System** - 5 built-in themes with custom theme support
|
|
43
|
+
- **Internationalization** - Built-in 8 languages, easily extensible
|
|
44
|
+
- **Progress Management** - Visual progress bars with drag-to-adjust
|
|
45
|
+
- **Interactive Operations** - Task dragging, resizing, parent-child linkage
|
|
46
|
+
- **Responsive Design** - Adjustable split panel ratio
|
|
47
|
+
- **High Performance** - Virtual scrolling optimization for large datasets
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Clone repository
|
|
53
|
+
git clone <repository-url>
|
|
54
|
+
|
|
55
|
+
# Install dependencies
|
|
56
|
+
npm install
|
|
57
|
+
|
|
58
|
+
# Start development server
|
|
59
|
+
npm run dev
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Dependencies
|
|
63
|
+
|
|
64
|
+
- @vueuse/core ^13.0.0
|
|
65
|
+
- dayjs ^1.11.13
|
|
66
|
+
- interactjs ^1.10.27
|
|
67
|
+
- svg.js ^2.7.1
|
|
68
|
+
- vue ^3.5.13
|
|
69
|
+
- zod ^3.24.2
|
|
70
|
+
|
|
71
|
+
## Basic Usage
|
|
72
|
+
|
|
73
|
+
```vue
|
|
74
|
+
<template>
|
|
75
|
+
<gantt
|
|
76
|
+
:styleConfig="styleConfig"
|
|
77
|
+
:dataConfig="dataConfig"
|
|
78
|
+
:eventConfig="eventConfig"
|
|
79
|
+
/>
|
|
80
|
+
</template>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { ref, onMounted } from 'vue';
|
|
86
|
+
import dayjs from 'dayjs';
|
|
87
|
+
import Gantt, {
|
|
88
|
+
type DataConfig,
|
|
89
|
+
type StyleConfig,
|
|
90
|
+
type EventConfig
|
|
91
|
+
} from './components/gantt/Gantt.vue';
|
|
92
|
+
import { LinkType } from './components/gantt/Types';
|
|
93
|
+
|
|
94
|
+
// Style configuration
|
|
95
|
+
const styleConfig = ref<StyleConfig>({
|
|
96
|
+
headersHeight: 100, // Header height
|
|
97
|
+
rowHeight: 60, // Row height
|
|
98
|
+
setBarColor: (row) => {
|
|
99
|
+
// Custom task bar color
|
|
100
|
+
const colorMap = {
|
|
101
|
+
'urgent': 'red',
|
|
102
|
+
'important': 'blue',
|
|
103
|
+
'normal': 'gray'
|
|
104
|
+
};
|
|
105
|
+
return colorMap[row.level] ?? 'black';
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Data configuration
|
|
110
|
+
const dataConfig = ref<DataConfig>({
|
|
111
|
+
queryStartDate: '',
|
|
112
|
+
queryEndDate: '',
|
|
113
|
+
dataSource: [],
|
|
114
|
+
dependencies: [],
|
|
115
|
+
mapFields: {
|
|
116
|
+
id: 'id',
|
|
117
|
+
parentId: 'pid',
|
|
118
|
+
task: 'taskNo',
|
|
119
|
+
priority: 'level',
|
|
120
|
+
startdate: 'start_date',
|
|
121
|
+
enddate: 'end_date',
|
|
122
|
+
takestime: 'spend_time',
|
|
123
|
+
progress: 'job_progress'
|
|
124
|
+
},
|
|
125
|
+
taskHeaders: [
|
|
126
|
+
{ title: 'No.', width: 80, property: 'no', show: true },
|
|
127
|
+
{ title: 'Task Name', width: 190, property: 'task', show: true },
|
|
128
|
+
{ title: 'Priority', width: 90, property: 'priority', show: true },
|
|
129
|
+
{ title: 'Start Date', width: 150, property: 'startdate', show: true },
|
|
130
|
+
{ title: 'End Date', width: 150, property: 'enddate', show: true },
|
|
131
|
+
{ title: 'Duration', width: 90, property: 'takestime', show: true }
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Event configuration
|
|
136
|
+
const eventConfig = ref<EventConfig>({
|
|
137
|
+
addRootTask: (row) => console.log('Add root task', row),
|
|
138
|
+
addSubTask: (task) => console.log('Add subtask', task),
|
|
139
|
+
removeTask: (task) => console.log('Remove task', task),
|
|
140
|
+
editTask: (task) => console.log('Edit task', task),
|
|
141
|
+
queryTask: async (startDate, endDate, mode) => {
|
|
142
|
+
// Query task data
|
|
143
|
+
dataConfig.value.dataSource = await fetchTasks(startDate, endDate);
|
|
144
|
+
},
|
|
145
|
+
barDate: (id, startDate, endDate) => {
|
|
146
|
+
console.log('Task date changed', id, startDate, endDate);
|
|
147
|
+
},
|
|
148
|
+
allowChangeTaskDate: (allow) => {
|
|
149
|
+
console.log('Allow date change', allow);
|
|
150
|
+
},
|
|
151
|
+
updateProgress: (detail) => {
|
|
152
|
+
console.log('Progress updated', detail);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
onMounted(() => {
|
|
157
|
+
const startDate = dayjs().startOf('month').format('YYYY-MM-DD');
|
|
158
|
+
const endDate = dayjs().endOf('month').format('YYYY-MM-DD');
|
|
159
|
+
eventConfig.value.queryTask(startDate, endDate, 'Month');
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Configuration Details
|
|
164
|
+
|
|
165
|
+
### StyleConfig
|
|
166
|
+
|
|
167
|
+
| Property | Type | Default | Description |
|
|
168
|
+
|----------|------|---------|-------------|
|
|
169
|
+
| headersHeight | number | 100 | Header area height (pixels) |
|
|
170
|
+
| rowHeight | number | 60 | Row height (pixels) |
|
|
171
|
+
| setBarColor | function | - | Callback function for custom task bar colors |
|
|
172
|
+
|
|
173
|
+
### DataConfig
|
|
174
|
+
|
|
175
|
+
| Property | Type | Description |
|
|
176
|
+
|----------|------|-------------|
|
|
177
|
+
| queryStartDate | string | Query start date (YYYY-MM-DD) |
|
|
178
|
+
| queryEndDate | string | Query end date (YYYY-MM-DD) |
|
|
179
|
+
| dataSource | array | Task data source |
|
|
180
|
+
| dependencies | array | Task dependencies |
|
|
181
|
+
| mapFields | object | Field mapping configuration |
|
|
182
|
+
| taskHeaders | array | Left task table column configuration |
|
|
183
|
+
|
|
184
|
+
#### mapFields Field Mapping
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
{
|
|
188
|
+
id: 'id', // Task ID field
|
|
189
|
+
parentId: 'pid', // Parent task ID field (for hierarchy)
|
|
190
|
+
task: 'taskNo', // Task name field
|
|
191
|
+
priority: 'level', // Priority field
|
|
192
|
+
startdate: 'start_date', // Start date field
|
|
193
|
+
enddate: 'end_date', // End date field
|
|
194
|
+
takestime: 'spend_time', // Duration field
|
|
195
|
+
progress: 'job_progress' // Progress field (0-1)
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### taskHeaders Header Configuration
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
{
|
|
203
|
+
title: string; // Column title
|
|
204
|
+
width: number; // Column width
|
|
205
|
+
property: string; // Corresponds to property name in mapFields
|
|
206
|
+
show: boolean; // Whether to display
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
### EventConfig
|
|
212
|
+
|
|
213
|
+
| Event | Parameters | Description |
|
|
214
|
+
|-------|------------|-------------|
|
|
215
|
+
| addRootTask | (row) | Triggered when adding a root task |
|
|
216
|
+
| addSubTask | (task) | Triggered when adding a subtask |
|
|
217
|
+
| removeTask | (task) | Triggered when removing a task |
|
|
218
|
+
| editTask | (task) | Triggered when editing a task |
|
|
219
|
+
| queryTask | (startDate, endDate, mode) | Triggered when querying tasks |
|
|
220
|
+
| barDate | (id, startDate, endDate) | Triggered when task date changes |
|
|
221
|
+
| allowChangeTaskDate | (allow) | Whether task date modification is allowed |
|
|
222
|
+
| updateProgress | (detail) | Triggered when progress is updated |
|
|
223
|
+
|
|
224
|
+
#### updateProgress Event Details
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
interface ProgressUpdateDetail {
|
|
228
|
+
taskId: any; // Task ID
|
|
229
|
+
oldProgress: number; // Old progress value (0-1)
|
|
230
|
+
newProgress: number; // New progress value (0-1)
|
|
231
|
+
task: object; // Complete task object
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Task Data Format
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
{
|
|
239
|
+
id: '1', // Task ID
|
|
240
|
+
pid: '0', // Parent task ID, '0' means root task
|
|
241
|
+
taskNo: 'Project Planning Phase', // Task name
|
|
242
|
+
level: 'Important', // Priority
|
|
243
|
+
start_date: '2024-12-01 08:00:00', // Start time
|
|
244
|
+
end_date: '2024-12-06 18:00:00', // End time
|
|
245
|
+
job_progress: '0.85', // Progress (0-1)
|
|
246
|
+
spend_time: null // Duration (auto-calculated)
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Task Dependencies
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
Finish-Start (FS) Start-Start (SS) Finish-Finish (FF) Start-Finish (SF)
|
|
254
|
+
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
|
|
255
|
+
│ Task A │──┐ │ Task A │──┐ │ Task A │──┐ │ Task A │◄─┐
|
|
256
|
+
└─────────┘ │ └─────────┘ │ └─────────┘ │ └─────────┘ │
|
|
257
|
+
▼ ▼ ▼ │
|
|
258
|
+
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
|
|
259
|
+
│ Task B │ │ Task B │ │ Task B │ │ Task B │
|
|
260
|
+
└─────────┘ └─────────┘ └─────────┘ └─────────┘
|
|
261
|
+
B starts after A and B start A and B finish B starts
|
|
262
|
+
A finishes together together before A ends
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Dependency Types
|
|
266
|
+
|
|
267
|
+
| Type | Enum | Description |
|
|
268
|
+
|------|------|-------------|
|
|
269
|
+
| Finish-Start (FS) | FINISH_TO_START | Successor task starts after predecessor finishes |
|
|
270
|
+
| Start-Start (SS) | START_TO_START | Tasks start simultaneously |
|
|
271
|
+
| Finish-Finish (FF) | FINISH_TO_FINISH | Tasks finish simultaneously |
|
|
272
|
+
| Start-Finish (SF) | START_TO_FINISH | Predecessor finishes after successor starts |
|
|
273
|
+
|
|
274
|
+
### Configuration Example
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import { LinkType } from './components/gantt/Types';
|
|
278
|
+
|
|
279
|
+
dependencies: [
|
|
280
|
+
// Task 2 starts after Task 1 finishes
|
|
281
|
+
{ sourceTaskId: '1', targetTaskId: '2', type: LinkType.FINISH_TO_START },
|
|
282
|
+
|
|
283
|
+
// Task 3 and Task 4 start simultaneously
|
|
284
|
+
{ sourceTaskId: '3', targetTaskId: '4', type: LinkType.START_TO_START },
|
|
285
|
+
|
|
286
|
+
// Task 5 and Task 6 must finish simultaneously
|
|
287
|
+
{ sourceTaskId: '5', targetTaskId: '6', type: LinkType.FINISH_TO_FINISH },
|
|
288
|
+
]
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## View Modes
|
|
292
|
+
|
|
293
|
+
| Mode | Time Unit | Header Example | Use Case |
|
|
294
|
+
|------|-----------|----------------|----------|
|
|
295
|
+
| 🗓️ **Month** | Day | `01 02 03 04 05 ...` | Long-term project planning |
|
|
296
|
+
| 📅 **Day** | Day | `Mon Tue Wed ...` | Short-term task management |
|
|
297
|
+
| 📊 **Week** | Week | `W50 W51 W52 ...` | Mid-term project tracking |
|
|
298
|
+
| ⏰ **Hour** | Hour | `08 09 10 11 12 ...` | Precise task scheduling |
|
|
299
|
+
|
|
300
|
+
The component supports four time granularity views:
|
|
301
|
+
|
|
302
|
+
| Mode | Description | Use Case |
|
|
303
|
+
|------|-------------|----------|
|
|
304
|
+
| Month | Display by day, month unit | Long-term project planning |
|
|
305
|
+
| Day | Display by day, precise to day | Short-term task management |
|
|
306
|
+
| Week | Display by week | Mid-term project tracking |
|
|
307
|
+
| Hour | Display by hour | Precise task scheduling |
|
|
308
|
+
|
|
309
|
+
## Theme System
|
|
310
|
+
|
|
311
|
+
| Theme | Primary Color | Style Features |
|
|
312
|
+
|-------|---------------|----------------|
|
|
313
|
+
| 🔷 **Metro** | `#0078d4` | Microsoft Metro design language, professional metallic texture |
|
|
314
|
+
| 🌙 **Dark** | `#00d4ff` | Eye-friendly dark theme, suitable for extended use |
|
|
315
|
+
| ✨ **Modern** | `#6366f1` | Clean modern design, refreshing and comfortable |
|
|
316
|
+
| 💼 **Classic** | `#2563eb` | Traditional business style, stable and dignified |
|
|
317
|
+
| 🎨 **Colorful** | `#f59e0b` | Vibrant colorful theme, full of vitality |
|
|
318
|
+
|
|
319
|
+
### Built-in Themes
|
|
320
|
+
|
|
321
|
+
| Theme ID | Name | Description |
|
|
322
|
+
|----------|------|-------------|
|
|
323
|
+
| metro | Metro | Microsoft Metro design language |
|
|
324
|
+
| dark | Dark Mode | Eye-friendly dark theme |
|
|
325
|
+
| modern | Modern | Clean modern design |
|
|
326
|
+
| classic | Classic | Traditional business style |
|
|
327
|
+
| colorful | Colorful | Vibrant colorful theme |
|
|
328
|
+
|
|
329
|
+
### Switching Themes
|
|
330
|
+
|
|
331
|
+
A theme selector is provided in the top right corner of the component. Click to switch themes. Theme settings are automatically saved to localStorage.
|
|
332
|
+
|
|
333
|
+
### Custom Theme CSS Variables
|
|
334
|
+
|
|
335
|
+
```css
|
|
336
|
+
:root {
|
|
337
|
+
--primary: #0078d4; /* Primary color */
|
|
338
|
+
--primary-dark: #106ebe; /* Primary color dark */
|
|
339
|
+
--primary-light: #1084d8; /* Primary color light */
|
|
340
|
+
--bg-content: #ffffff; /* Content background color */
|
|
341
|
+
--bg-metal-light: linear-gradient(145deg, #ffffff, #f5f5f5);
|
|
342
|
+
--bg-metal-normal: linear-gradient(145deg, #f5f5f5, #e8e8e8);
|
|
343
|
+
--border: #d0d0d0; /* Border color */
|
|
344
|
+
--text-primary: #333333; /* Primary text color */
|
|
345
|
+
--text-secondary: #666666; /* Secondary text color */
|
|
346
|
+
--row-hover: #FFF3A1; /* Row hover color */
|
|
347
|
+
--font-family: 'Segoe UI', sans-serif;
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## Internationalization Support
|
|
352
|
+
|
|
353
|
+
The component has a built-in complete internationalization (i18n) system, supporting bilingual switching between Chinese and English, and can easily extend more languages.
|
|
354
|
+
|
|
355
|
+
### Supported Languages
|
|
356
|
+
|
|
357
|
+
| Language | Code | Status |
|
|
358
|
+
|----------|------|--------|
|
|
359
|
+
| 🇨🇳 Simplified Chinese | zh-CN | ✅ Full support |
|
|
360
|
+
| 🇺🇸 English | en-US | ✅ Full support |
|
|
361
|
+
| 🇯🇵 Japanese | ja-JP | ✅ Full support |
|
|
362
|
+
| 🇰🇷 Korean | ko-KR | ✅ Full support |
|
|
363
|
+
| 🇫🇷 French | fr-FR | ✅ Full support |
|
|
364
|
+
| 🇩🇪 German | de-DE | ✅ Full support |
|
|
365
|
+
| 🇪🇸 Spanish | es-ES | ✅ Full support |
|
|
366
|
+
| 🇷🇺 Russian | ru-RU | ✅ Full support |
|
|
367
|
+
|
|
368
|
+
### Usage
|
|
369
|
+
|
|
370
|
+
#### 1. Switch Language
|
|
371
|
+
|
|
372
|
+
In the top right corner of the Gantt chart toolbar, click the language selector to switch the interface language:
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { setLocale } from './components/gantt/i18n';
|
|
376
|
+
|
|
377
|
+
// Switch to English
|
|
378
|
+
setLocale('en-US');
|
|
379
|
+
|
|
380
|
+
// Switch to Chinese
|
|
381
|
+
setLocale('zh-CN');
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
#### 2. Get Current Language
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
import { getLocale } from './components/gantt/i18n';
|
|
388
|
+
|
|
389
|
+
const currentLang = getLocale(); // 'zh-CN' or 'en-US'
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
#### 3. Use Translation in Components
|
|
393
|
+
|
|
394
|
+
```vue
|
|
395
|
+
<script setup lang="ts">
|
|
396
|
+
import { useI18n } from './components/gantt/i18n';
|
|
397
|
+
|
|
398
|
+
const { t, locale } = useI18n();
|
|
399
|
+
</script>
|
|
400
|
+
|
|
401
|
+
<template>
|
|
402
|
+
<div>
|
|
403
|
+
<h1>{{ t('common.title') }}</h1>
|
|
404
|
+
<button>{{ t('common.confirm') }}</button>
|
|
405
|
+
<p>{{ t('task.name') }}</p>
|
|
406
|
+
</div>
|
|
407
|
+
</template>
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### i18n Features
|
|
411
|
+
|
|
412
|
+
- ✅ **Instant Switching** - No page refresh required to switch languages
|
|
413
|
+
- ✅ **Auto Save** - Language selection automatically saved to browser localStorage
|
|
414
|
+
- ✅ **Complete Coverage** - All interface text has been translated
|
|
415
|
+
- ✅ **Dynamic Headers** - Timeline headers (months, weekdays, etc.) automatically formatted based on language
|
|
416
|
+
- ✅ **Type Safe** - TypeScript provides complete type support
|
|
417
|
+
- ✅ **Easy Extension** - Can easily add new language support
|
|
418
|
+
|
|
419
|
+
### Translated Interface Elements
|
|
420
|
+
|
|
421
|
+
#### Toolbar
|
|
422
|
+
- Date picker separator ("to" / "至")
|
|
423
|
+
- View mode buttons (Month/Week/Day/Hour)
|
|
424
|
+
- Link legend title and all link types
|
|
425
|
+
|
|
426
|
+
#### Task Headers
|
|
427
|
+
- No. (序号)
|
|
428
|
+
- Task Name (任务名称)
|
|
429
|
+
- Priority (优先级)
|
|
430
|
+
- Start Date (开始时间)
|
|
431
|
+
- End Date (结束时间)
|
|
432
|
+
- Duration (耗时)
|
|
433
|
+
- Progress (进度)
|
|
434
|
+
|
|
435
|
+
#### Timeline Headers
|
|
436
|
+
- Month names (January/一月, February/二月...)
|
|
437
|
+
- Weekday names (Monday/星期一, Tuesday/星期二...)
|
|
438
|
+
- Date format (01/01日, 02/02日...)
|
|
439
|
+
- Hour format (0:00/0点, 1:00/1点...)
|
|
440
|
+
- Week title (Week 1/第1周)
|
|
441
|
+
|
|
442
|
+
#### Configuration Panel
|
|
443
|
+
- Gantt configuration title
|
|
444
|
+
- Theme settings options
|
|
445
|
+
- All link configuration options
|
|
446
|
+
- All buttons and labels
|
|
447
|
+
|
|
448
|
+
### Adding New Languages
|
|
449
|
+
|
|
450
|
+
To add new language support, follow these steps:
|
|
451
|
+
|
|
452
|
+
1. Create a new language file in the `src/components/gantt/i18n/locales/` directory (e.g., `ja-JP.ts`)
|
|
453
|
+
2. Copy the structure from `zh-CN.ts` or `en-US.ts`
|
|
454
|
+
3. Translate all text
|
|
455
|
+
4. Import and register the new language in `src/components/gantt/i18n/index.ts`:
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
import jaJP from './locales/ja-JP';
|
|
459
|
+
import koKR from './locales/ko-KR';
|
|
460
|
+
import frFR from './locales/fr-FR';
|
|
461
|
+
import deDE from './locales/de-DE';
|
|
462
|
+
import esES from './locales/es-ES';
|
|
463
|
+
import ruRU from './locales/ru-RU';
|
|
464
|
+
|
|
465
|
+
const messages: Record<Locale, Messages> = {
|
|
466
|
+
'zh-CN': zhCN,
|
|
467
|
+
'en-US': enUS,
|
|
468
|
+
'ja-JP': jaJP, // Added Japanese
|
|
469
|
+
'ko-KR': koKR, // Added Korean
|
|
470
|
+
'fr-FR': frFR, // Added French
|
|
471
|
+
'de-DE': deDE, // Added German
|
|
472
|
+
'es-ES': esES, // Added Spanish
|
|
473
|
+
'ru-RU': ruRU // Added Russian
|
|
474
|
+
};
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
5. Update the `getLocales()` function to add new language options
|
|
478
|
+
|
|
479
|
+
### Language Pack Structure
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
export default {
|
|
483
|
+
common: { // Common text
|
|
484
|
+
confirm: 'Confirm',
|
|
485
|
+
cancel: 'Cancel',
|
|
486
|
+
// ...
|
|
487
|
+
},
|
|
488
|
+
date: { // Date and time
|
|
489
|
+
year: 'Year',
|
|
490
|
+
month: 'Month',
|
|
491
|
+
// ...
|
|
492
|
+
},
|
|
493
|
+
viewMode: { // View mode
|
|
494
|
+
month: 'Month',
|
|
495
|
+
week: 'Week',
|
|
496
|
+
// ...
|
|
497
|
+
},
|
|
498
|
+
task: { // Task related
|
|
499
|
+
name: 'Task Name',
|
|
500
|
+
priority: 'Priority',
|
|
501
|
+
// ...
|
|
502
|
+
},
|
|
503
|
+
// More categories...
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
## Interactive Features
|
|
509
|
+
|
|
510
|
+
| Operation | Description | Effect |
|
|
511
|
+
|-----------|-------------|--------|
|
|
512
|
+
| 🖱️ **Drag & Move** | Drag entire task bar | Modify task start and end dates |
|
|
513
|
+
| 📏 **Resize** | Drag task bar left/right edges | Adjust task duration |
|
|
514
|
+
| 📊 **Progress Adjust** | Drag triangle slider at bottom of task bar | Adjust task completion progress |
|
|
515
|
+
|
|
516
|
+
### Task Bar Operations
|
|
517
|
+
|
|
518
|
+
- **Drag & Move** - Drag task bar to modify start and end dates
|
|
519
|
+
- **Resize** - Drag task bar left/right edges to adjust duration
|
|
520
|
+
- **Progress Adjust** - Drag triangle slider at bottom to adjust progress
|
|
521
|
+
|
|
522
|
+
### Parent-Child Task Linkage
|
|
523
|
+
|
|
524
|
+
- Moving parent tasks causes child tasks to move along
|
|
525
|
+
- Resizing parent tasks checks child task constraints
|
|
526
|
+
- Child tasks cannot start before parent tasks
|
|
527
|
+
|
|
528
|
+
### Quick Operations
|
|
529
|
+
|
|
530
|
+
- Click the **+** button in the top left to add root tasks
|
|
531
|
+
- Click the calendar icon to jump to today
|
|
532
|
+
- Right-click task rows to add subtasks, edit, or delete
|
|
533
|
+
|
|
534
|
+
## Link Configuration
|
|
535
|
+
|
|
536
|
+
### Link Styles
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
interface LinkConfig {
|
|
540
|
+
color: string; // Link color
|
|
541
|
+
width: number; // Link width
|
|
542
|
+
dashArray?: string; // Dash style
|
|
543
|
+
showArrow: boolean; // Show arrow
|
|
544
|
+
arrowSize: number; // Arrow size
|
|
545
|
+
showLabels: boolean; // Show labels
|
|
546
|
+
pathType: LinkPathType; // Path type
|
|
547
|
+
cornerRadius: number; // Corner radius
|
|
548
|
+
smoothCorners: boolean; // Smooth corners
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Path Types
|
|
553
|
+
|
|
554
|
+
```
|
|
555
|
+
Straight Bezier Curve Right Angle
|
|
556
|
+
┌─────┐ ┌─────┐ ┌─────┐
|
|
557
|
+
│Task A│ ────────▶│Task A│ ╭───────▶ │Task A│ ┐
|
|
558
|
+
└─────┘ └─────┘ ╰─┐ └─────┘ │
|
|
559
|
+
│ │
|
|
560
|
+
┌─────┐ ┌─────┐
|
|
561
|
+
│Task B│ │Task B│
|
|
562
|
+
└─────┘ └─────┘
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
| Type | Enum | Description |
|
|
566
|
+
|------|------|-------------|
|
|
567
|
+
| Straight | STRAIGHT | Direct connection |
|
|
568
|
+
| Bezier Curve | BEZIER | Smooth curve |
|
|
569
|
+
| Right Angle | RIGHT_ANGLE | Right-angle connection |
|
|
570
|
+
|
|
571
|
+
## Performance Optimization
|
|
572
|
+
|
|
573
|
+
The component includes multiple performance optimizations:
|
|
574
|
+
|
|
575
|
+
- **Virtual Scrolling** - Only render tasks in the visible area
|
|
576
|
+
- **Throttled Updates** - Use throttling to avoid frequent re-renders when data changes
|
|
577
|
+
- **Cached Calculations** - Use computed to cache complex calculation results
|
|
578
|
+
- **On-Demand Rendering** - Calculate and render elements like links on demand
|
|
579
|
+
|
|
580
|
+
## Project Structure
|
|
581
|
+
|
|
582
|
+
```
|
|
583
|
+
src/
|
|
584
|
+
├── components/
|
|
585
|
+
│ └── gantt/
|
|
586
|
+
│ ├── Gantt.vue # Main component
|
|
587
|
+
│ ├── Bar.vue # Task bar component
|
|
588
|
+
│ ├── BarRecursionRow.vue # Recursive row component
|
|
589
|
+
│ ├── TaskLinks.vue # Link component
|
|
590
|
+
│ ├── TimelineHeader.vue # Timeline header
|
|
591
|
+
│ ├── TableContent.vue # Table content
|
|
592
|
+
│ ├── RightTable.vue # Right Gantt chart area
|
|
593
|
+
│ ├── SplitPane.vue # Split panel
|
|
594
|
+
│ ├── DatePicker.vue # Date picker
|
|
595
|
+
│ ├── GanttConfigPanel.vue # Configuration panel
|
|
596
|
+
│ ├── GanttThemeSelector.vue # Theme selector
|
|
597
|
+
│ ├── LanguageSelector.vue # Language selector
|
|
598
|
+
│ ├── LinkConfigPanel.vue # Link configuration panel
|
|
599
|
+
│ ├── Types.ts # Type definitions
|
|
600
|
+
│ ├── Store.ts # State management
|
|
601
|
+
│ ├── ShareState.ts # Shared state
|
|
602
|
+
│ ├── LinkConfig.ts # Link configuration
|
|
603
|
+
│ ├── Symbols.ts # Injection symbols
|
|
604
|
+
│ ├── ZodSchema.ts # Data validation
|
|
605
|
+
│ ├── i18n/ # Internationalization system
|
|
606
|
+
│ │ ├── index.ts # i18n core
|
|
607
|
+
│ │ └── locales/ # Language packs
|
|
608
|
+
│ │ ├── zh-CN.ts # Chinese language pack
|
|
609
|
+
│ │ ├── en-US.ts # English language pack
|
|
610
|
+
│ │ ├── ja-JP.ts # Japanese language pack
|
|
611
|
+
│ │ ├── ko-KR.ts # Korean language pack
|
|
612
|
+
│ │ ├── fr-FR.ts # French language pack
|
|
613
|
+
│ │ ├── de-DE.ts # German language pack
|
|
614
|
+
│ │ ├── es-ES.ts # Spanish language pack
|
|
615
|
+
│ │ └── ru-RU.ts # Russian language pack
|
|
616
|
+
│ ├── task/ # Task-related components
|
|
617
|
+
│ │ ├── TaskTable.vue
|
|
618
|
+
│ │ ├── TaskHeader.vue
|
|
619
|
+
│ │ ├── TaskContent.vue
|
|
620
|
+
│ │ └── TaskRow.vue
|
|
621
|
+
│ └── themes/ # Theme configuration
|
|
622
|
+
│ └── GanttThemes.ts
|
|
623
|
+
├── App.vue # Example application
|
|
624
|
+
├── main.ts # Entry file
|
|
625
|
+
└── style.css # Global styles
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
## Complete Example
|
|
629
|
+
|
|
630
|
+
Refer to `src/App.vue` for a complete usage example, including:
|
|
631
|
+
|
|
632
|
+
- Multi-level task structure
|
|
633
|
+
- Various dependency configurations
|
|
634
|
+
- Custom color mapping
|
|
635
|
+
- Event handling
|
|
636
|
+
- Internationalization integration
|
|
637
|
+
|
|
638
|
+
## Browser Support
|
|
639
|
+
|
|
640
|
+
- Chrome (Recommended)
|
|
641
|
+
- Firefox
|
|
642
|
+
- Safari
|
|
643
|
+
- Edge
|
|
644
|
+
|
|
645
|
+
## License
|
|
646
|
+
|
|
647
|
+
MIT
|