jordium-gantt-vue3 1.4.2 → 1.4.4

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.md CHANGED
@@ -2,7 +2,10 @@
2
2
 
3
3
  <p align="center">
4
4
  <a href="https://www.npmjs.com/package/jordium-gantt-vue3">
5
- <img src="https://img.shields.io/npm/v/jordium-gantt-vue3.svg" alt="npm version">
5
+ <img src="https://img.shields.io/npm/v/jordium-gantt-vue3?style=flat-square" alt="npm version">
6
+ </a>
7
+ <a href="https://www.npmjs.com/package/jordium-gantt-vue3">
8
+ <img src="https://img.shields.io/npm/dt/jordium-gantt-vue3?style=flat-square" alt="npm total">
6
9
  </a>
7
10
  <a href="https://opensource.org/licenses/MIT">
8
11
  <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License">
@@ -21,6 +24,7 @@
21
24
  <p align="center">
22
25
  <a href="./README.md">中文</a> |
23
26
  <a href="./README-EN.md">English</a>
27
+ <a href="./CHANGELOG.md">更新日志</a>
24
28
  </p>
25
29
 
26
30
  <p align="center">现代化的 Vue 3 甘特图组件库,为项目管理和任务调度提供完整解决方案</p>
@@ -105,10 +109,7 @@ import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
105
109
  ```vue
106
110
  <template>
107
111
  <div style="height: 600px;">
108
- <GanttChart
109
- :tasks="tasks"
110
- :milestones="milestones"
111
- />
112
+ <GanttChart :tasks="tasks" :milestones="milestones" />
112
113
  </div>
113
114
  </template>
114
115
 
@@ -123,7 +124,7 @@ const tasks = ref([
123
124
  name: '项目启动',
124
125
  startDate: '2025-01-01',
125
126
  endDate: '2025-01-10',
126
- progress: 100
127
+ progress: 100,
127
128
  },
128
129
  {
129
130
  id: 2,
@@ -131,7 +132,7 @@ const tasks = ref([
131
132
  startDate: '2025-01-11',
132
133
  endDate: '2025-01-20',
133
134
  progress: 80,
134
- predecessor: [1]
135
+ predecessor: [1],
135
136
  },
136
137
  {
137
138
  id: 3,
@@ -139,8 +140,8 @@ const tasks = ref([
139
140
  startDate: '2025-01-21',
140
141
  endDate: '2025-02-05',
141
142
  progress: 50,
142
- predecessor: [2]
143
- }
143
+ predecessor: [2],
144
+ },
144
145
  ])
145
146
 
146
147
  const milestones = ref([
@@ -148,8 +149,8 @@ const milestones = ref([
148
149
  id: 101,
149
150
  name: '项目立项',
150
151
  date: '2025-01-01',
151
- type: 'milestone'
152
- }
152
+ type: 'milestone',
153
+ },
153
154
  ])
154
155
  </script>
155
156
  ```
@@ -158,6 +159,7 @@ const milestones = ref([
158
159
  <span><strong>推荐使用 <a href="https://dovee.cc/a.php?anaxjgyz1ozZq2B">DOVE</a> VPN,快速、稳定。</strong></span> <span style="color:red;">(注意:请合法使用 VPN 资源)</span>
159
160
 
160
161
  ## 🌞 NPM包使用示例
162
+
161
163
  请参考项目下的npm-demo,这是一个独立的项目,可以使用IDE单独浏览和启动,运行前请安装element plus以及jordium-gantt-vue3插件包
162
164
 
163
165
  ```bash
@@ -166,9 +168,10 @@ npm install element-plus
166
168
  npm install jordium-gantt-vue3
167
169
  npm run dev
168
170
  ```
171
+
169
172
  ---
170
173
 
171
- ## 组件指南
174
+ ## 组件指南
172
175
 
173
176
  ### GanttChart 组件
174
177
 
@@ -176,68 +179,71 @@ npm run dev
176
179
 
177
180
  #### 基础属性
178
181
 
179
- | 属性名 | 类型 | 默认值 | 说明 |
180
- |--------|------|--------|------|
181
- | `tasks` | `Task[]` | `[]` | 任务数据数组 |
182
- | `milestones` | `Task[]` | `[]` | 里程碑数据数组(注意:类型为 Task[],需设置 type='milestone') |
183
- | `showToolbar` | `boolean` | `true` | 是否显示工具栏 |
184
- | `useDefaultDrawer` | `boolean` | `true` | 是否使用内置任务编辑抽屉(TaskDrawer) |
185
- | `useDefaultMilestoneDialog` | `boolean` | `true` | 是否使用内置里程碑编辑对话框(MilestoneDialog) |
186
- | `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
187
- | `allowDragAndResize` | `boolean` | `true` | 是否允许拖拽和调整任务/里程碑大小 |
182
+ | 属性名 | 类型 | 默认值 | 说明 |
183
+ | --------------------------- | --------- | ------- | -------------------------------------------------------------- |
184
+ | `tasks` | `Task[]` | `[]` | 任务数据数组 |
185
+ | `milestones` | `Task[]` | `[]` | 里程碑数据数组(注意:类型为 Task[],需设置 type='milestone') |
186
+ | `showToolbar` | `boolean` | `true` | 是否显示工具栏 |
187
+ | `useDefaultDrawer` | `boolean` | `true` | 是否使用内置任务编辑抽屉(TaskDrawer) |
188
+ | `useDefaultMilestoneDialog` | `boolean` | `true` | 是否使用内置里程碑编辑对话框(MilestoneDialog) |
189
+ | `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
190
+ | `allowDragAndResize` | `boolean` | `true` | 是否允许拖拽和调整任务/里程碑大小 |
191
+ | `enableTaskRowMove` | `boolean` | `false` | 是否允许拖拽和摆放TaskRow |
188
192
 
189
193
  #### 配置对象属性
190
194
 
191
195
  完整的配置对象说明请参考 [⚙️ 配置与扩展](#⚙️-配置与扩展) 章节。
192
196
 
193
- | 属性名 | 类型 | 默认值 | 说明 |
194
- |--------|------|--------|------|
195
- | `toolbarConfig` | `ToolbarConfig` | `{}` | 工具栏配置 |
196
- | `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置 |
197
- | `taskBarConfig` | `TaskBarConfig` | `undefined` | 任务条样式配置 |
198
- | `localeMessages` | `Partial<Messages['zh-CN']>` | `undefined` | 自定义多语言配置 |
199
- | `workingHours` | `WorkingHours` | `{ morning: { start: 8, end: 11 }, afternoon: { start: 13, end: 17 } }` | 工作时间配置 |
197
+ | 属性名 | 类型 | 默认值 | 说明 |
198
+ | ---------------- | ---------------------------- | ----------------------------------------------------------------------- | ---------------- |
199
+ | `toolbarConfig` | `ToolbarConfig` | `{}` | 工具栏配置 |
200
+ | `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置 |
201
+ | `taskBarConfig` | `TaskBarConfig` | `undefined` | 任务条样式配置 |
202
+ | `localeMessages` | `Partial<Messages['zh-CN']>` | `undefined` | 自定义多语言配置 |
203
+ | `workingHours` | `WorkingHours` | `{ morning: { start: 8, end: 11 }, afternoon: { start: 13, end: 17 } }` | 工作时间配置 |
200
204
 
201
205
  #### 回调函数属性
202
206
 
203
- | 属性名 | 类型 | 说明 |
204
- |--------|------|------|
205
- | `onTodayLocate` | `() => void` | 工具栏"今天"按钮点击回调 |
206
- | `onExportCsv` | `() => boolean \| void` | 工具栏"导出CSV"按钮点击回调,返回 `false` 可阻止默认导出 |
207
- | `onExportPdf` | `() => void` | 工具栏"导出PDF"按钮点击回调 |
208
- | `onLanguageChange` | `(lang: 'zh-CN' \| 'en-US') => void` | 语言切换回调 |
209
- | `onThemeChange` | `(isDark: boolean) => void` | 主题切换回调 |
210
- | `onFullscreenChange` | `(isFullscreen: boolean) => void` | 全屏切换回调 |
211
- | `onExpandAll` | `() => void` | 工具栏"全部展开"按钮点击回调 |
212
- | `onCollapseAll` | `() => void` | 工具栏"全部折叠"按钮点击回调 |
207
+ | 属性名 | 类型 | 说明 |
208
+ | -------------------- | ------------------------------------ | -------------------------------------------------------- |
209
+ | `onTodayLocate` | `() => void` | 工具栏"今天"按钮点击回调 |
210
+ | `onExportCsv` | `() => boolean \| void` | 工具栏"导出CSV"按钮点击回调,返回 `false` 可阻止默认导出 |
211
+ | `onExportPdf` | `() => void` | 工具栏"导出PDF"按钮点击回调 |
212
+ | `onLanguageChange` | `(lang: 'zh-CN' \| 'en-US') => void` | 语言切换回调 |
213
+ | `onThemeChange` | `(isDark: boolean) => void` | 主题切换回调 |
214
+ | `onFullscreenChange` | `(isFullscreen: boolean) => void` | 全屏切换回调 |
215
+ | `onExpandAll` | `() => void` | 工具栏"全部展开"按钮点击回调 |
216
+ | `onCollapseAll` | `() => void` | 工具栏"全部折叠"按钮点击回调 |
213
217
 
214
218
  #### 组件事件(Events)
215
219
 
216
220
  完整的事件说明请分别参考:
221
+
217
222
  - **任务相关事件**:参见下方 [任务管理](#任务管理) 章节
218
223
  - **里程碑相关事件**:参见下方 [里程碑管理](#里程碑管理) 章节
219
224
 
220
225
  **事件列表总览:**
221
226
 
222
- | 事件名 | 参数 | 说明 |
223
- |--------|------|------|
224
- | `add-task` | - | 点击工具栏"添加任务"按钮 |
225
- | `task-click` | `(task: Task, event: MouseEvent)` | 点击任务 |
226
- | `task-double-click` | `(task: Task)` | 双击任务 |
227
- | `task-added` | `{ task: Task }` | 任务添加后触发 |
228
- | `task-updated` | `{ task: Task }` | 任务更新后触发 |
229
- | `task-deleted` | `{ task: Task }` | 任务删除后触发 |
230
- | `taskbar-drag-end` | `(task: Task)` | 拖拽任务结束 |
231
- | `taskbar-resize-end` | `(task: Task)` | 调整任务大小结束 |
232
- | `predecessor-added` | `{ targetTask, newTask }` | 添加前置任务 |
233
- | `successor-added` | `{ targetTask, newTask }` | 添加后置任务 |
234
- | `timer-started` | `(task: Task)` | 任务计时器启动 |
235
- | `timer-stopped` | `(task: Task)` | 任务计时器停止 |
236
- | `add-milestone` | - | 点击工具栏"添加里程碑"按钮 |
237
- | `milestone-saved` | `(milestone: Task)` | 里程碑保存 |
238
- | `milestone-deleted` | `{ milestoneId: number }` | 里程碑删除 |
239
- | `milestone-icon-changed` | `{ milestoneId, icon }` | 里程碑图标变更 |
240
- | `milestone-drag-end` | `(milestone: Task)` | 拖拽里程碑结束 |
227
+ | 事件名 | 参数 | 说明 |
228
+ | ------------------------ | --------------------------------- | -------------------------- |
229
+ | `add-task` | - | 点击工具栏"添加任务"按钮 |
230
+ | `task-click` | `(task: Task, event: MouseEvent)` | 点击任务 |
231
+ | `task-double-click` | `(task: Task)` | 双击任务 |
232
+ | `task-added` | `{ task: Task }` | 任务添加后触发 |
233
+ | `task-updated` | `{ task: Task }` | 任务更新后触发 |
234
+ | `task-deleted` | `{ task: Task }` | 任务删除后触发 |
235
+ | `taskbar-drag-end` | `(task: Task)` | 拖拽任务结束 |
236
+ | `taskbar-resize-end` | `(task: Task)` | 调整任务大小结束 |
237
+ | `predecessor-added` | `{ targetTask, newTask }` | 添加前置任务 |
238
+ | `successor-added` | `{ targetTask, newTask }` | 添加后置任务 |
239
+ | `timer-started` | `(task: Task)` | 任务计时器启动 |
240
+ | `timer-stopped` | `(task: Task)` | 任务计时器停止 |
241
+ | `add-milestone` | - | 点击工具栏"添加里程碑"按钮 |
242
+ | `milestone-saved` | `(milestone: Task)` | 里程碑保存 |
243
+ | `milestone-deleted` | `{ milestoneId: number }` | 里程碑删除 |
244
+ | `milestone-icon-changed` | `{ milestoneId, icon }` | 里程碑图标变更 |
245
+ | `milestone-drag-end` | `(milestone: Task)` | 拖拽里程碑结束 |
246
+ | `task-row-moved` | `payload: { draggedTask: Task, targetTask: Task, position: 'after' 或 'child'}` | 拖拽TaskRow结束 |
241
247
 
242
248
  #### 示例1:最简单的甘特图
243
249
 
@@ -259,8 +265,8 @@ const tasks = ref([
259
265
  name: '任务1',
260
266
  startDate: '2025-01-01',
261
267
  endDate: '2025-01-10',
262
- progress: 100
263
- }
268
+ progress: 100,
269
+ },
264
270
  ])
265
271
  </script>
266
272
  ```
@@ -270,10 +276,7 @@ const tasks = ref([
270
276
  ```vue
271
277
  <template>
272
278
  <div style="height: 600px;">
273
- <GanttChart
274
- :tasks="tasks"
275
- :milestones="milestones"
276
- />
279
+ <GanttChart :tasks="tasks" :milestones="milestones" />
277
280
  </div>
278
281
  </template>
279
282
 
@@ -288,8 +291,8 @@ const tasks = ref([
288
291
  name: '项目启动',
289
292
  startDate: '2025-01-01',
290
293
  endDate: '2025-01-10',
291
- progress: 100
292
- }
294
+ progress: 100,
295
+ },
293
296
  ])
294
297
 
295
298
  const milestones = ref([
@@ -298,8 +301,8 @@ const milestones = ref([
298
301
  name: '项目立项',
299
302
  startDate: '2025-01-01',
300
303
  type: 'milestone',
301
- icon: 'diamond'
302
- }
304
+ icon: 'diamond',
305
+ },
303
306
  ])
304
307
  </script>
305
308
  ```
@@ -314,10 +317,10 @@ const milestones = ref([
314
317
  <button @click="addTask">新增任务</button>
315
318
  <button @click="addMilestone">新增里程碑</button>
316
319
  </div>
317
-
320
+
318
321
  <!-- 甘特图组件,隐藏内置工具栏 -->
319
322
  <div style="height: 600px;">
320
- <GanttChart
323
+ <GanttChart
321
324
  :tasks="tasks"
322
325
  :milestones="milestones"
323
326
  :show-toolbar="false"
@@ -342,7 +345,7 @@ const addTask = () => {
342
345
  name: '新任务',
343
346
  startDate: new Date().toISOString().split('T')[0],
344
347
  endDate: new Date().toISOString().split('T')[0],
345
- progress: 0
348
+ progress: 0,
346
349
  }
347
350
  tasks.value.push(newTask)
348
351
  }
@@ -352,16 +355,16 @@ const addMilestone = () => {
352
355
  id: Date.now(),
353
356
  name: '新里程碑',
354
357
  startDate: new Date().toISOString().split('T')[0],
355
- type: 'milestone'
358
+ type: 'milestone',
356
359
  }
357
360
  milestones.value.push(newMilestone)
358
361
  }
359
362
 
360
- const handleTaskAdded = (e) => {
363
+ const handleTaskAdded = e => {
361
364
  console.log('任务已添加:', e.task)
362
365
  }
363
366
 
364
- const handleMilestoneSaved = (milestone) => {
367
+ const handleMilestoneSaved = milestone => {
365
368
  console.log('里程碑已保存:', milestone)
366
369
  }
367
370
  </script>
@@ -375,37 +378,38 @@ const handleMilestoneSaved = (milestone) => {
375
378
 
376
379
  #### Task 数据结构
377
380
 
378
- | 字段名 | 类型 | 必填 | 默认值 | 说明 |
379
- |--------|------|------|--------|------|
380
- | `id` | `number` | ✅ | - | 任务唯一标识符 |
381
- | `name` | `string` | ✅ | - | 任务名称 |
382
- | `startDate` | `string` | - | - | 开始日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
383
- | `endDate` | `string` | - | - | 结束日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
384
- | `progress` | `number` | - | `0` | 任务进度,范围 0-100 |
385
- | `predecessor` | `number[]` | - | - | 前置任务 ID 数组,标准格式:`[1, 2, 3]`<br/>**兼容格式**:也支持字符串 `'1,2,3'` 或字符串数组 `['1', '2', '3']`,组件会自动解析 |
386
- | `assignee` | `string` | - | - | 任务负责人 |
387
- | `avatar` | `string` | - | - | 任务负责人头像 URL |
388
- | `estimatedHours` | `number` | - | - | 预估工时(小时) |
389
- | `actualHours` | `number` | - | - | 实际工时(小时) |
390
- | `parentId` | `number` | - | - | 父任务 ID,用于任务分组 |
391
- | `children` | `Task[]` | - | - | 子任务数组 |
392
- | `collapsed` | `boolean` | - | `false` | 子任务是否折叠 |
393
- | `isParent` | `boolean` | - | - | 是否为父任务 |
394
- | `type` | `string` | - | - | 任务类型,'milestone' 表示里程碑,'milestone-group' 表示里程碑分组 |
395
- | `description` | `string` | - | - | 任务描述 |
396
- | `icon` | `string` | - | `'diamond'` | 任务图标(用于里程碑),可选值:'diamond', 'flag', 'star', 'rocket' 等 |
397
- | `level` | `number` | - | `0` | 任务层级(自动计算) |
398
- | `isTimerRunning` | `boolean` | - | `false` | 计时器是否运行中 |
399
- | `timerStartTime` | `number` | - | - | 计时开始时间(时间戳) |
400
- | `timerEndTime` | `number` | - | - | 计时结束时间(时间戳) |
401
- | `timerStartDesc` | `string` | - | - | 计时开始时填写的描述 |
402
- | `timerElapsedTime` | `number` | - | `0` | 已计时的时长(毫秒) |
403
- | `isEditable` | `boolean` | - | `true` | 单个任务是否可编辑(可拖拽、拉伸),优先级高于全局 `allowDragAndResize` |
404
- | `[key: string]` | `unknown` | - | - | 支持自定义属性扩展,可添加任意额外字段 |
381
+ | 字段名 | 类型 | 必填 | 默认值 | 说明 |
382
+ | ------------------ | ---------- | ---- | ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
383
+ | `id` | `number` | ✅ | - | 任务唯一标识符 |
384
+ | `name` | `string` | ✅ | - | 任务名称 |
385
+ | `startDate` | `string` | - | - | 开始日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
386
+ | `endDate` | `string` | - | - | 结束日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
387
+ | `progress` | `number` | - | `0` | 任务进度,范围 0-100 |
388
+ | `predecessor` | `number[]` | - | - | 前置任务 ID 数组,标准格式:`[1, 2, 3]`<br/>**兼容格式**:也支持字符串 `'1,2,3'` 或字符串数组 `['1', '2', '3']`,组件会自动解析 |
389
+ | `assignee` | `string` | - | - | 任务负责人 |
390
+ | `avatar` | `string` | - | - | 任务负责人头像 URL |
391
+ | `estimatedHours` | `number` | - | - | 预估工时(小时) |
392
+ | `actualHours` | `number` | - | - | 实际工时(小时) |
393
+ | `parentId` | `number` | - | - | 父任务 ID,用于任务分组 |
394
+ | `children` | `Task[]` | - | - | 子任务数组 |
395
+ | `collapsed` | `boolean` | - | `false` | 子任务是否折叠 |
396
+ | `isParent` | `boolean` | - | - | 是否为父任务 |
397
+ | `type` | `string` | - | - | 任务类型,'milestone' 表示里程碑,'milestone-group' 表示里程碑分组 |
398
+ | `description` | `string` | - | - | 任务描述 |
399
+ | `icon` | `string` | - | `'diamond'` | 任务图标(用于里程碑),可选值:'diamond', 'flag', 'star', 'rocket' 等 |
400
+ | `level` | `number` | - | `0` | 任务层级(自动计算) |
401
+ | `isTimerRunning` | `boolean` | - | `false` | 计时器是否运行中 |
402
+ | `timerStartTime` | `number` | - | - | 计时开始时间(时间戳) |
403
+ | `timerEndTime` | `number` | - | - | 计时结束时间(时间戳) |
404
+ | `timerStartDesc` | `string` | - | - | 计时开始时填写的描述 |
405
+ | `timerElapsedTime` | `number` | - | `0` | 已计时的时长(毫秒) |
406
+ | `isEditable` | `boolean` | - | `true` | 单个任务是否可编辑(可拖拽、拉伸),优先级高于全局 `allowDragAndResize` |
407
+ | `[key: string]` | `unknown` | - | - | 支持自定义属性扩展,可添加任意额外字段 |
405
408
 
406
409
  > **自定义属性扩展**:Task 接口支持添加任意自定义字段,例如:`priority`、`tags`、`status`、`department` 等业务相关字段。
407
- >
410
+ >
408
411
  > **前置任务字段说明**:
412
+ >
409
413
  > - **标准格式**(推荐):`predecessor: [1, 2, 3]` - number 数组
410
414
  > - **兼容格式1**:`predecessor: '1,2,3'` - 逗号分隔的字符串
411
415
  > - **兼容格式2**:`predecessor: ['1', '2', '3']` - 字符串数组
@@ -414,15 +418,17 @@ const handleMilestoneSaved = (milestone) => {
414
418
 
415
419
  #### 任务相关属性
416
420
 
417
- | 属性名 | 类型 | 默认值 | 说明 |
418
- |--------|------|--------|------|
419
- | `tasks` | `Task[]` | `[]` | 任务数据数组 |
420
- | `useDefaultDrawer` | `boolean` | `true` | 是否使用内置的任务编辑抽屉(TaskDrawer) |
421
- | `taskBarConfig` | `TaskBarConfig` | `{}` | 任务条样式配置,详见 [TaskBarConfig 配置](#taskbarconfig-配置) |
422
- | `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置,详见 [TaskListConfig 配置](#tasklistconfig-配置) |
423
- | `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
421
+ | 属性名 | 类型 | 默认值 | 说明 |
422
+ | --------------------- | ---------------- | ----------- | -------------------------------------------------------------- |
423
+ | `tasks` | `Task[]` | `[]` | 任务数据数组 |
424
+ | `useDefaultDrawer` | `boolean` | `true` | 是否使用内置的任务编辑抽屉(TaskDrawer) |
425
+ | `taskBarConfig` | `TaskBarConfig` | `{}` | 任务条样式配置,详见 [TaskBarConfig 配置](#taskbarconfig-配置) |
426
+ | `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置,详见 [TaskListConfig 配置](#tasklistconfig-配置) |
427
+ | `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
428
+ | `enableTaskRowMove` | `boolean` | `false` | 是否允许拖拽和摆放TaskRow
424
429
 
425
430
  **配置说明**:
431
+
426
432
  - **默认模式**:`useDefaultDrawer=true`(默认),双击任务自动打开内置 TaskDrawer
427
433
  - **自定义编辑器**:`useDefaultDrawer=false` 禁用内置抽屉,监听 `@task-double-click` 事件打开自定义编辑器
428
434
  - **只读模式**:`useDefaultDrawer=false` 且不监听 `@task-double-click` 事件,用户双击任务无反应
@@ -431,22 +437,24 @@ const handleMilestoneSaved = (milestone) => {
431
437
 
432
438
  > **💡 事件驱动架构**:组件采用纯事件驱动设计,所有用户操作(添加、编辑、删除、拖拽等)都会触发对应事件,方便外部监听和处理。
433
439
 
434
- | 事件名 | 参数 | 触发时机 | 说明 |
435
- |--------|------|---------|------|
436
- | `add-task` | - | 点击工具栏"添加任务"按钮时 | 可用于自定义新增任务逻辑。如 `useDefaultDrawer=true`,组件会自动打开内置 TaskDrawer |
437
- | `task-click` | `(task: Task, event: MouseEvent) => void` | 点击任务条时 | 单击任务触发 |
438
- | `task-double-click` | `(task: Task) => void` | 双击任务条时 | 双击任务时**始终触发**。`useDefaultDrawer=true` 时组件会额外打开内置编辑器,`false` 时不打开。事件触发与属性值无关 |
439
- | `task-added` | `{ task: Task }` | 任务添加后 | 通过内置 TaskDrawer 添加任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理(如调用 API 保存) |
440
- | `task-updated` | `{ task: Task }` | 任务更新后 | 通过内置 TaskDrawer 或拖拽更新任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理 |
441
- | `task-deleted` | `{ task: Task }` | 任务删除后 | 通过内置 TaskDrawer 删除任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理 |
442
- | `taskbar-drag-end` | `(task: Task) => void` | 拖拽任务条结束时 | 任务位置变化,startDate 和 endDate 已更新。**注意**:组件已自动更新 `tasks` 数据 |
443
- | `taskbar-resize-end` | `(task: Task) => void` | 调整任务条大小结束时 | 任务时长变化,endDate 已更新。**注意**:组件已自动更新 `tasks` 数据 |
444
- | `predecessor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加前置任务后 | `targetTask` 是被添加前置任务的任务,`newTask` 是新创建的前置任务 |
445
- | `successor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加后置任务后 | `targetTask` 是原任务,`newTask` 是新创建的后置任务(其 predecessor 已包含 targetTask.id) |
446
- | `timer-started` | `(task: Task) => void` | 任务计时器启动时 | 开始记录任务工时 |
447
- | `timer-stopped` | `(task: Task) => void` | 任务计时器停止时 | 停止记录任务工时 |
440
+ | 事件名 | 参数 | 触发时机 | 说明 |
441
+ | -------------------- | ----------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
442
+ | `add-task` | - | 点击工具栏"添加任务"按钮时 | 可用于自定义新增任务逻辑。如 `useDefaultDrawer=true`,组件会自动打开内置 TaskDrawer |
443
+ | `task-click` | `(task: Task, event: MouseEvent) => void` | 点击任务条时 | 单击任务触发 |
444
+ | `task-double-click` | `(task: Task) => void` | 双击任务条时 | 双击任务时**始终触发**。`useDefaultDrawer=true` 时组件会额外打开内置编辑器,`false` 时不打开。事件触发与属性值无关 |
445
+ | `task-added` | `{ task: Task }` | 任务添加后 | 通过内置 TaskDrawer 添加任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理(如调用 API 保存) |
446
+ | `task-updated` | `{ task: Task }` | 任务更新后 | 通过内置 TaskDrawer 或拖拽更新任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理 |
447
+ | `task-deleted` | `{ task: Task }` | 任务删除后 | 通过内置 TaskDrawer 删除任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理 |
448
+ | `taskbar-drag-end` | `(task: Task) => void` | 拖拽任务条结束时 | 任务位置变化,startDate 和 endDate 已更新。**注意**:组件已自动更新 `tasks` 数据 |
449
+ | `taskbar-resize-end` | `(task: Task) => void` | 调整任务条大小结束时 | 任务时长变化,endDate 已更新。**注意**:组件已自动更新 `tasks` 数据 |
450
+ | `predecessor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加前置任务后 | `targetTask` 是被添加前置任务的任务,`newTask` 是新创建的前置任务 |
451
+ | `successor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加后置任务后 | `targetTask` 是原任务,`newTask` 是新创建的后置任务(其 predecessor 已包含 targetTask.id) |
452
+ | `timer-started` | `(task: Task) => void` | 任务计时器启动时 | 开始记录任务工时 |
453
+ | `timer-stopped` | `(task: Task) => void` | 任务计时器停止时 | 停止记录任务工时 |
454
+ | `task-row-moved` | `payload: { draggedTask: Task, targetTask: Task, position: 'after' 或 'child'}` | 拖拽TaskRow结束 | TaskList中的TasRow按住拖拽,完成前后排放位置放置后
448
455
 
449
456
  **数据同步说明**:
457
+
450
458
  - ✅ **组件内部自动更新**:所有任务的增删改操作,组件都会自动更新 `props.tasks` 数据
451
459
  - ✅ **事件仅做通知**:外部监听事件主要用于:显示提示消息、调用后端 API、更新其他相关数据等
452
460
  - ❌ **避免重复操作**:不要在事件处理器中再次修改 `tasks` 数据,否则会导致重复更新
@@ -456,7 +464,7 @@ const handleMilestoneSaved = (milestone) => {
456
464
  ```vue
457
465
  <template>
458
466
  <div style="height: 600px;">
459
- <GanttChart
467
+ <GanttChart
460
468
  :tasks="tasks"
461
469
  @add-task="handleAddTask"
462
470
  @task-added="handleTaskAdded"
@@ -492,7 +500,7 @@ const tasks = ref<Task[]>([
492
500
  progress: 60,
493
501
  assignee: '李四',
494
502
  predecessor: [1], // 依赖任务1
495
- }
503
+ },
496
504
  ])
497
505
 
498
506
  // 工具栏"添加任务"按钮点击事件
@@ -545,7 +553,7 @@ const handleTaskDragEnd = (task: Task) => {
545
553
 
546
554
  ```vue
547
555
  <template>
548
- <GanttChart
556
+ <GanttChart
549
557
  :tasks="tasks"
550
558
  @predecessor-added="handlePredecessorAdded"
551
559
  @successor-added="handleSuccessorAdded"
@@ -565,7 +573,7 @@ const tasks = ref<Task[]>([
565
573
  startDate: '2025-01-01',
566
574
  endDate: '2025-01-10',
567
575
  progress: 100,
568
- predecessor: [] // 无前置任务
576
+ predecessor: [], // 无前置任务
569
577
  },
570
578
  {
571
579
  id: 2,
@@ -573,7 +581,7 @@ const tasks = ref<Task[]>([
573
581
  startDate: '2025-01-11',
574
582
  endDate: '2025-01-20',
575
583
  progress: 80,
576
- predecessor: [1] // 依赖任务1(需求分析)
584
+ predecessor: [1], // 依赖任务1(需求分析)
577
585
  },
578
586
  {
579
587
  id: 3,
@@ -581,7 +589,7 @@ const tasks = ref<Task[]>([
581
589
  startDate: '2025-01-11',
582
590
  endDate: '2025-01-18',
583
591
  progress: 90,
584
- predecessor: [1] // 依赖任务1
592
+ predecessor: [1], // 依赖任务1
585
593
  },
586
594
  {
587
595
  id: 4,
@@ -589,7 +597,7 @@ const tasks = ref<Task[]>([
589
597
  startDate: '2025-01-21',
590
598
  endDate: '2025-02-10',
591
599
  progress: 60,
592
- predecessor: [2] // 依赖任务2(系统设计)
600
+ predecessor: [2], // 依赖任务2(系统设计)
593
601
  },
594
602
  {
595
603
  id: 5,
@@ -597,7 +605,7 @@ const tasks = ref<Task[]>([
597
605
  startDate: '2025-01-19',
598
606
  endDate: '2025-02-08',
599
607
  progress: 70,
600
- predecessor: [2, 3] // 同时依赖任务2和3
608
+ predecessor: [2, 3], // 同时依赖任务2和3
601
609
  },
602
610
  {
603
611
  id: 6,
@@ -605,8 +613,8 @@ const tasks = ref<Task[]>([
605
613
  startDate: '2025-02-11',
606
614
  endDate: '2025-02-20',
607
615
  progress: 30,
608
- predecessor: [4, 5] // 依赖前端和后端开发完成
609
- }
616
+ predecessor: [4, 5], // 依赖前端和后端开发完成
617
+ },
610
618
  ])
611
619
 
612
620
  // 通过右键菜单添加前置任务时触发
@@ -628,6 +636,7 @@ const handleSuccessorAdded = (event: { targetTask: Task; newTask: Task }) => {
628
636
  ```
629
637
 
630
638
  **依赖关系说明**:
639
+
631
640
  - **`predecessor` 字段支持多种格式**:
632
641
  - 标准格式(推荐):`[1, 2, 3]` - number 数组
633
642
  - 兼容格式1:`'1,2,3'` - 逗号分隔的字符串
@@ -653,9 +662,9 @@ const handleSuccessorAdded = (event: { targetTask: Task; newTask: Task }) => {
653
662
  <button @click="triggerAddMilestone">新增里程碑</button>
654
663
  <!-- 其他自定义按钮... -->
655
664
  </div>
656
-
665
+
657
666
  <!-- 甘特图组件,隐藏内置工具栏 -->
658
- <GanttChart
667
+ <GanttChart
659
668
  :tasks="tasks"
660
669
  :milestones="milestones"
661
670
  :show-toolbar="false"
@@ -696,7 +705,7 @@ const handleAddMilestone = () => {
696
705
  console.log('准备新增里程碑(由自定义按钮触发)')
697
706
  }
698
707
 
699
- const handleTaskAdded = (e) => {
708
+ const handleTaskAdded = e => {
700
709
  console.log('任务已添加:', e.task)
701
710
  // 调用 API 保存...
702
711
  }
@@ -704,10 +713,103 @@ const handleTaskAdded = (e) => {
704
713
  ```
705
714
 
706
715
  > **💡 灵活性设计**:
716
+ >
707
717
  > - 显示工具栏 + 默认编辑器:最简单的开箱即用方式
708
718
  > - 隐藏工具栏 + 自定义按钮 + 默认编辑器:自定义控制栏样式,保留默认编辑功能
709
719
  > - 隐藏工具栏 + 自定义按钮 + 自定义编辑器:完全自定义所有交互逻辑
710
720
 
721
+ #### 示例4:任务行拖拽排序
722
+
723
+ 允许用户通过拖拽 TaskRow 来调整任务的层级关系和前后顺序:
724
+
725
+ ```vue
726
+ <template>
727
+ <div style="height: 600px;">
728
+ <GanttChart
729
+ :tasks="tasks"
730
+ :enable-task-row-move="true"
731
+ @task-row-moved="handleTaskRowMoved"
732
+ />
733
+ </div>
734
+ </template>
735
+
736
+ <script setup lang="ts">
737
+ import { ref } from 'vue'
738
+ import { GanttChart } from 'jordium-gantt-vue3'
739
+ import type { Task } from 'jordium-gantt-vue3'
740
+ import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
741
+
742
+ const tasks = ref<Task[]>([
743
+ {
744
+ id: 1,
745
+ name: '项目规划',
746
+ startDate: '2025-01-01',
747
+ endDate: '2025-01-10',
748
+ progress: 100,
749
+ },
750
+ {
751
+ id: 2,
752
+ name: '需求分析',
753
+ startDate: '2025-01-11',
754
+ endDate: '2025-01-20',
755
+ progress: 60,
756
+ parentId: 1,
757
+ },
758
+ {
759
+ id: 3,
760
+ name: '系统设计',
761
+ startDate: '2025-01-21',
762
+ endDate: '2025-01-30',
763
+ progress: 40,
764
+ },
765
+ ])
766
+
767
+ // 任务行拖拽完成事件
768
+ const handleTaskRowMoved = (payload: {
769
+ draggedTask: Task
770
+ targetTask: Task
771
+ position: 'after' | 'child'
772
+ }) => {
773
+ const { draggedTask, targetTask, position } = payload
774
+
775
+ console.log(`任务 [${draggedTask.name}] 被拖拽到任务 [${targetTask.name}] ${position === 'after' ? '之后' : '下方作为子任务'}`)
776
+
777
+ // 组件已自动更新任务的层级关系和位置
778
+ // position === 'after': 任务被放置在目标任务之后(同级)
779
+ // position === 'child': 任务被放置为目标任务的子任务(第一个子任务位置)
780
+
781
+ // 这里可以:
782
+ // 1. 显示确认对话框,让用户确认是否移动
783
+ // 2. 调用后端 API 保存新的任务层级关系
784
+ // 3. 更新相关的依赖关系
785
+
786
+ // 示例:调用后端 API
787
+ // await api.updateTaskHierarchy({
788
+ // taskId: draggedTask.id,
789
+ // targetTaskId: targetTask.id,
790
+ // position: position
791
+ // })
792
+ }
793
+ </script>
794
+ ```
795
+
796
+ **拖拽排序说明**:
797
+
798
+ - **启用拖拽**:设置 `enable-task-row-move="true"` 启用任务行拖拽功能(默认为 `false`)
799
+ - **拖拽算法**:
800
+ - **算法1(放置在后面)**:当目标任务没有子任务时,被拖拽的任务会放置在目标任务之后(同级),`position='after'`
801
+ - **算法2(作为子任务)**:当目标任务有子任务时,被拖拽的任务会成为目标任务的第一个子任务,`position='child'`
802
+ - **视觉反馈**:
803
+ - 拖拽时会显示半透明的跟随元素
804
+ - 悬停在有效目标任务上时显示蓝色边框提示
805
+ - 无子任务的任务显示蓝色底部边框
806
+ - 有子任务的任务显示蓝色四周边框
807
+ - **自动更新**:组件会自动更新任务的 `parentId` 字段和 `children` 数组,外部只需监听事件做额外处理(如保存到后端)
808
+ - **限制条件**:
809
+ - 不能拖拽到自己身上
810
+ - 不能拖拽到自己的子任务上(避免循环引用)
811
+ - 里程碑和里程碑分组不能被拖拽
812
+
711
813
  ### 里程碑管理
712
814
 
713
815
  里程碑用于标记项目中的重要时间节点,如项目启动、阶段完成、产品发布等。组件提供了灵活的里程碑编辑配置,默认使用内置的 MilestoneDialog,也支持完全自定义编辑行为。
@@ -716,32 +818,34 @@ const handleTaskAdded = (e) => {
716
818
 
717
819
  #### Milestone 数据结构
718
820
 
719
- | 字段名 | 类型 | 必填 | 默认值 | 说明 |
720
- |--------|------|------|--------|------|
721
- | `id` | `number` | ✅ | - | 里程碑唯一标识符 |
722
- | `name` | `string` | ✅ | - | 里程碑名称 |
723
- | `startDate` | `string` | ✅ | - | 里程碑日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
724
- | `endDate` | `string` | - | - | 结束日期(通常里程碑不需要,自动设置为与 startDate 相同) |
725
- | `assignee` | `string` | - | - | 负责人 |
726
- | `type` | `string` | ✅ | `'milestone'` | 类型标识,必须设为 'milestone' |
727
- | `icon` | `string` | - | `'diamond'` | 里程碑图标,可选值:'diamond', 'flag', 'star', 'rocket' 等 |
728
- | `description` | `string` | - | - | 里程碑描述 |
821
+ | 字段名 | 类型 | 必填 | 默认值 | 说明 |
822
+ | ------------- | -------- | ---- | ------------- | ---------------------------------------------------------- |
823
+ | `id` | `number` | ✅ | - | 里程碑唯一标识符 |
824
+ | `name` | `string` | ✅ | - | 里程碑名称 |
825
+ | `startDate` | `string` | ✅ | - | 里程碑日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
826
+ | `endDate` | `string` | - | - | 结束日期(通常里程碑不需要,自动设置为与 startDate 相同) |
827
+ | `assignee` | `string` | - | - | 负责人 |
828
+ | `type` | `string` | ✅ | `'milestone'` | 类型标识,必须设为 'milestone' |
829
+ | `icon` | `string` | - | `'diamond'` | 里程碑图标,可选值:'diamond', 'flag', 'star', 'rocket' 等 |
830
+ | `description` | `string` | - | - | 里程碑描述 |
729
831
 
730
832
  > **注意**:`milestones` 属性的类型为 `Task[]`,需要确保每个里程碑对象的 `type` 字段设置为 `'milestone'`。
731
833
 
732
834
  #### 里程碑相关属性
733
835
 
734
- | 属性名 | 类型 | 默认值 | 说明 |
735
- |--------|------|--------|------|
736
- | `milestones` | `Task[]` | `[]` | 里程碑数据数组(类型为 Task[],需确保 type='milestone') |
737
- | `useDefaultMilestoneDialog` | `boolean` | `true` | 是否使用内置的里程碑编辑对话框(MilestoneDialog) |
836
+ | 属性名 | 类型 | 默认值 | 说明 |
837
+ | --------------------------- | --------- | ------ | -------------------------------------------------------- |
838
+ | `milestones` | `Task[]` | `[]` | 里程碑数据数组(类型为 Task[],需确保 type='milestone') |
839
+ | `useDefaultMilestoneDialog` | `boolean` | `true` | 是否使用内置的里程碑编辑对话框(MilestoneDialog) |
738
840
 
739
841
  **配置说明**:
842
+
740
843
  - **默认模式**:`useDefaultMilestoneDialog=true`(默认),双击里程碑自动打开内置 MilestoneDialog
741
844
  - **禁用编辑器**:`useDefaultMilestoneDialog=false`,双击里程碑无反应(组件不打开任何编辑器)
742
845
  - **自定义编辑器**:可以监听 `onMilestoneDoubleClick` 回调或相关事件,实现自定义编辑逻辑
743
846
 
744
847
  > **💡 里程碑与任务的区别**:
848
+ >
745
849
  > - 里程碑数据通过 `milestones` 属性独立管理,与 `tasks` 分开
746
850
  > - 里程碑对象的 `type` 字段必须设置为 `'milestone'`
747
851
  > - 里程碑不支持子任务、依赖关系等复杂结构
@@ -751,20 +855,20 @@ const handleTaskAdded = (e) => {
751
855
 
752
856
  > **⚠️ 已废弃**:请使用新的事件驱动 API(见下方"里程碑事件"章节)
753
857
 
754
-
755
858
  #### 里程碑事件
756
859
 
757
860
  > **💡 事件驱动架构**:里程碑管理采用事件驱动设计,推荐使用事件 API 替代回调函数。
758
861
 
759
- | 事件名 | 参数 | 触发时机 | 说明 |
760
- |--------|------|---------|------|
761
- | `add-milestone` | - | 点击工具栏"添加里程碑"按钮时 | 可用于自定义新增里程碑逻辑。如 `useDefaultMilestoneDialog=true`,组件会自动打开内置 MilestoneDialog |
762
- | `milestone-saved` | `(milestone: Task) => void` | 里程碑保存后(新增或编辑) | 通过内置 MilestoneDialog 保存里程碑后触发。**注意**:组件已自动更新 `milestones` 数据,外部只需监听此事件做额外处理(如调用 API 保存) |
763
- | `milestone-deleted` | `{ milestoneId: number }` | 里程碑删除后 | 通过内置 MilestoneDialog 删除里程碑后触发。**注意**:组件已自动更新 `milestones` 数据,外部只需监听此事件做额外处理 |
764
- | `milestone-icon-changed` | `{ milestoneId: number, icon: string }` | 里程碑图标变更后 | 通过内置 MilestoneDialog 修改图标后触发 |
765
- | `milestone-drag-end` | `(milestone: Task) => void` | 拖拽里程碑结束时 | 里程碑日期已更新。**注意**:组件已自动更新 `milestones` 数据 |
862
+ | 事件名 | 参数 | 触发时机 | 说明 |
863
+ | ------------------------ | --------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
864
+ | `add-milestone` | - | 点击工具栏"添加里程碑"按钮时 | 可用于自定义新增里程碑逻辑。如 `useDefaultMilestoneDialog=true`,组件会自动打开内置 MilestoneDialog |
865
+ | `milestone-saved` | `(milestone: Task) => void` | 里程碑保存后(新增或编辑) | 通过内置 MilestoneDialog 保存里程碑后触发。**注意**:组件已自动更新 `milestones` 数据,外部只需监听此事件做额外处理(如调用 API 保存) |
866
+ | `milestone-deleted` | `{ milestoneId: number }` | 里程碑删除后 | 通过内置 MilestoneDialog 删除里程碑后触发。**注意**:组件已自动更新 `milestones` 数据,外部只需监听此事件做额外处理 |
867
+ | `milestone-icon-changed` | `{ milestoneId: number, icon: string }` | 里程碑图标变更后 | 通过内置 MilestoneDialog 修改图标后触发 |
868
+ | `milestone-drag-end` | `(milestone: Task) => void` | 拖拽里程碑结束时 | 里程碑日期已更新。**注意**:组件已自动更新 `milestones` 数据 |
766
869
 
767
870
  **数据同步说明**:
871
+
768
872
  - ✅ **组件内部自动更新**:所有里程碑的增删改操作,组件都会自动更新 `props.milestones` 数据
769
873
  - ✅ **事件仅做通知**:外部监听事件主要用于:显示提示消息、调用后端 API、更新其他相关数据等
770
874
  - ❌ **避免重复操作**:不要在事件处理器中再次修改 `milestones` 数据,否则会导致重复更新
@@ -776,7 +880,7 @@ const handleTaskAdded = (e) => {
776
880
  ```vue
777
881
  <template>
778
882
  <div style="height: 600px;">
779
- <GanttChart
883
+ <GanttChart
780
884
  :milestones="milestones"
781
885
  @add-milestone="handleAddMilestone"
782
886
  @milestone-saved="handleMilestoneSaved"
@@ -801,15 +905,15 @@ const milestones = ref<Task[]>([
801
905
  type: 'milestone',
802
906
  icon: 'diamond',
803
907
  assignee: '项目经理',
804
- description: '项目正式启动'
908
+ description: '项目正式启动',
805
909
  },
806
910
  {
807
911
  id: 102,
808
912
  name: '需求评审',
809
913
  startDate: '2025-01-15',
810
914
  type: 'milestone',
811
- icon: 'flag'
812
- }
915
+ icon: 'flag',
916
+ },
813
917
  ])
814
918
 
815
919
  // 工具栏"添加里程碑"按钮点击事件
@@ -857,7 +961,7 @@ const handleMilestoneDrag = (milestone: Task) => {
857
961
  ```vue
858
962
  <template>
859
963
  <div style="height: 600px;">
860
- <GanttChart
964
+ <GanttChart
861
965
  :milestones="milestones"
862
966
  :use-default-milestone-dialog="false"
863
967
  @add-milestone="handleAddMilestone"
@@ -865,7 +969,7 @@ const handleMilestoneDrag = (milestone: Task) => {
865
969
  @milestone-deleted="handleMilestoneDeleted"
866
970
  @milestone-drag-end="handleMilestoneDrag"
867
971
  />
868
-
972
+
869
973
  <!-- 自定义里程碑编辑对话框 -->
870
974
  <CustomMilestoneDialog
871
975
  v-model:visible="customDialogVisible"
@@ -892,8 +996,8 @@ const milestones = ref<Task[]>([
892
996
  type: 'milestone',
893
997
  icon: 'diamond',
894
998
  assignee: '项目经理',
895
- description: '项目正式启动'
896
- }
999
+ description: '项目正式启动',
1000
+ },
897
1001
  ])
898
1002
 
899
1003
  const customDialogVisible = ref(false)
@@ -923,10 +1027,10 @@ const handleCustomDialogSave = (milestone: Task) => {
923
1027
  const newMilestone = {
924
1028
  ...milestone,
925
1029
  id: Date.now(), // 生成新 ID
926
- type: 'milestone'
1030
+ type: 'milestone',
927
1031
  }
928
1032
  milestones.value.push(newMilestone)
929
-
1033
+
930
1034
  // 调用后端 API 保存
931
1035
  // await api.createMilestone(newMilestone)
932
1036
  } else {
@@ -935,11 +1039,11 @@ const handleCustomDialogSave = (milestone: Task) => {
935
1039
  if (index !== -1) {
936
1040
  milestones.value[index] = { ...milestone }
937
1041
  }
938
-
1042
+
939
1043
  // 调用后端 API 更新
940
1044
  // await api.updateMilestone(milestone)
941
1045
  }
942
-
1046
+
943
1047
  customDialogVisible.value = false
944
1048
  }
945
1049
 
@@ -949,10 +1053,10 @@ const handleCustomDialogDelete = (milestoneId: number) => {
949
1053
  if (index !== -1) {
950
1054
  milestones.value.splice(index, 1)
951
1055
  }
952
-
1056
+
953
1057
  // 调用后端 API 删除
954
1058
  // await api.deleteMilestone(milestoneId)
955
-
1059
+
956
1060
  customDialogVisible.value = false
957
1061
  }
958
1062
 
@@ -989,7 +1093,7 @@ const handleMilestoneDrag = (milestone: Task) => {
989
1093
  <el-form-item label="里程碑名称">
990
1094
  <el-input v-model="form.name" placeholder="请输入里程碑名称" />
991
1095
  </el-form-item>
992
-
1096
+
993
1097
  <el-form-item label="日期">
994
1098
  <el-date-picker
995
1099
  v-model="form.startDate"
@@ -998,11 +1102,11 @@ const handleMilestoneDrag = (milestone: Task) => {
998
1102
  value-format="YYYY-MM-DD"
999
1103
  />
1000
1104
  </el-form-item>
1001
-
1105
+
1002
1106
  <el-form-item label="负责人">
1003
1107
  <el-input v-model="form.assignee" placeholder="请输入负责人" />
1004
1108
  </el-form-item>
1005
-
1109
+
1006
1110
  <el-form-item label="图标">
1007
1111
  <el-select v-model="form.icon" placeholder="选择图标">
1008
1112
  <el-option label="钻石" value="diamond" />
@@ -1011,22 +1115,15 @@ const handleMilestoneDrag = (milestone: Task) => {
1011
1115
  <el-option label="火箭" value="rocket" />
1012
1116
  </el-select>
1013
1117
  </el-form-item>
1014
-
1118
+
1015
1119
  <el-form-item label="描述">
1016
- <el-input
1017
- v-model="form.description"
1018
- type="textarea"
1019
- :rows="3"
1020
- placeholder="请输入描述"
1021
- />
1120
+ <el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入描述" />
1022
1121
  </el-form-item>
1023
1122
  </el-form>
1024
-
1123
+
1025
1124
  <template #footer>
1026
1125
  <div class="dialog-footer">
1027
- <el-button v-if="!isNew" type="danger" @click="handleDelete">
1028
- 删除
1029
- </el-button>
1126
+ <el-button v-if="!isNew" type="danger" @click="handleDelete"> 删除 </el-button>
1030
1127
  <el-button @click="handleClose">取消</el-button>
1031
1128
  <el-button type="primary" @click="handleSave">保存</el-button>
1032
1129
  </div>
@@ -1059,31 +1156,34 @@ const form = ref({
1059
1156
  assignee: '',
1060
1157
  icon: 'diamond',
1061
1158
  description: '',
1062
- type: 'milestone'
1159
+ type: 'milestone',
1063
1160
  })
1064
1161
 
1065
- watch(() => props.visible, (val) => {
1066
- dialogVisible.value = val
1067
- if (val) {
1068
- if (props.milestone) {
1069
- // 编辑模式,填充数据
1070
- form.value = { ...props.milestone }
1071
- } else {
1072
- // 新增模式,重置表单
1073
- form.value = {
1074
- id: 0,
1075
- name: '',
1076
- startDate: new Date().toISOString().split('T')[0],
1077
- assignee: '',
1078
- icon: 'diamond',
1079
- description: '',
1080
- type: 'milestone'
1162
+ watch(
1163
+ () => props.visible,
1164
+ val => {
1165
+ dialogVisible.value = val
1166
+ if (val) {
1167
+ if (props.milestone) {
1168
+ // 编辑模式,填充数据
1169
+ form.value = { ...props.milestone }
1170
+ } else {
1171
+ // 新增模式,重置表单
1172
+ form.value = {
1173
+ id: 0,
1174
+ name: '',
1175
+ startDate: new Date().toISOString().split('T')[0],
1176
+ assignee: '',
1177
+ icon: 'diamond',
1178
+ description: '',
1179
+ type: 'milestone',
1180
+ }
1081
1181
  }
1082
1182
  }
1083
1183
  }
1084
- })
1184
+ )
1085
1185
 
1086
- watch(dialogVisible, (val) => {
1186
+ watch(dialogVisible, val => {
1087
1187
  emit('update:visible', val)
1088
1188
  })
1089
1189
 
@@ -1108,6 +1208,7 @@ const handleDelete = () => {
1108
1208
  ```
1109
1209
 
1110
1210
  > **💡 自定义对话框说明**:
1211
+ >
1111
1212
  > - 设置 `use-default-milestone-dialog="false"` 禁用内置对话框
1112
1213
  > - 监听 `@add-milestone` 事件打开自定义对话框
1113
1214
  > - 需要手动管理 `milestones` 数组的增删改
@@ -1128,20 +1229,20 @@ const handleDelete = () => {
1128
1229
 
1129
1230
  **类型定义:**
1130
1231
 
1131
- | 字段名 | 类型 | 默认值 | 说明 |
1132
- |--------|------|--------|------|
1133
- | `showAddTask` | `boolean` | `true` | 显示"添加任务"按钮 |
1134
- | `showAddMilestone` | `boolean` | `true` | 显示"添加里程碑"按钮 |
1135
- | `showTodayLocate` | `boolean` | `true` | 显示"定位到今天"按钮 |
1136
- | `showExportCsv` | `boolean` | `true` | 显示"导出 CSV"按钮 |
1137
- | `showExportPdf` | `boolean` | `true` | 显示"导出 PDF"按钮 |
1138
- | `showLanguage` | `boolean` | `true` | 显示"语言切换"按钮(中/英文) |
1139
- | `showTheme` | `boolean` | `true` | 显示"主题切换"按钮(亮色/暗色) |
1140
- | `showFullscreen` | `boolean` | `true` | 显示"全屏"按钮 |
1141
- | `showTimeScale` | `boolean` | `true` | 显示时间刻度按钮组(控制整组按钮的显隐) |
1232
+ | 字段名 | 类型 | 默认值 | 说明 |
1233
+ | --------------------- | ----------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
1234
+ | `showAddTask` | `boolean` | `true` | 显示"添加任务"按钮 |
1235
+ | `showAddMilestone` | `boolean` | `true` | 显示"添加里程碑"按钮 |
1236
+ | `showTodayLocate` | `boolean` | `true` | 显示"定位到今天"按钮 |
1237
+ | `showExportCsv` | `boolean` | `true` | 显示"导出 CSV"按钮 |
1238
+ | `showExportPdf` | `boolean` | `true` | 显示"导出 PDF"按钮 |
1239
+ | `showLanguage` | `boolean` | `true` | 显示"语言切换"按钮(中/英文) |
1240
+ | `showTheme` | `boolean` | `true` | 显示"主题切换"按钮(亮色/暗色) |
1241
+ | `showFullscreen` | `boolean` | `true` | 显示"全屏"按钮 |
1242
+ | `showTimeScale` | `boolean` | `true` | 显示时间刻度按钮组(控制整组按钮的显隐) |
1142
1243
  | `timeScaleDimensions` | `TimelineScale[]` | `['hour', 'day', 'week', 'month', 'quarter', 'year']` | 设置时间刻度按钮组要显示的维度,可选值:`'hour'`、`'day'`、`'week'`、`'month'`、`'quarter'`、`'year'` |
1143
- | `defaultTimeScale` | `TimelineScale` | `'week'` | 默认选中的时间刻度 |
1144
- | `showExpandCollapse` | `boolean` | `true` | 显示"全部展开/折叠"按钮(用于父子任务树形结构) |
1244
+ | `defaultTimeScale` | `TimelineScale` | `'week'` | 默认选中的时间刻度 |
1245
+ | `showExpandCollapse` | `boolean` | `true` | 显示"全部展开/折叠"按钮(用于父子任务树形结构) |
1145
1246
 
1146
1247
  **TimelineScale 类型说明:**
1147
1248
 
@@ -1151,22 +1252,19 @@ type TimelineScale = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'
1151
1252
  // 也可以使用常量形式
1152
1253
  import { TimelineScale } from 'jordium-gantt-vue3'
1153
1254
 
1154
- TimelineScale.HOUR // 'hour' - 小时视图
1155
- TimelineScale.DAY // 'day' - 日视图
1156
- TimelineScale.WEEK // 'week' - 周视图
1157
- TimelineScale.MONTH // 'month' - 月视图
1255
+ TimelineScale.HOUR // 'hour' - 小时视图
1256
+ TimelineScale.DAY // 'day' - 日视图
1257
+ TimelineScale.WEEK // 'week' - 周视图
1258
+ TimelineScale.MONTH // 'month' - 月视图
1158
1259
  TimelineScale.QUARTER // 'quarter' - 季度视图
1159
- TimelineScale.YEAR // 'year' - 年视图
1260
+ TimelineScale.YEAR // 'year' - 年视图
1160
1261
  ```
1161
1262
 
1162
1263
  **示例1:完整配置(显示所有功能)**
1163
1264
 
1164
1265
  ```vue
1165
1266
  <template>
1166
- <GanttChart
1167
- :tasks="tasks"
1168
- :toolbar-config="toolbarConfig"
1169
- />
1267
+ <GanttChart :tasks="tasks" :toolbar-config="toolbarConfig" />
1170
1268
  </template>
1171
1269
 
1172
1270
  <script setup lang="ts">
@@ -1175,20 +1273,26 @@ import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
1175
1273
  import type { ToolbarConfig } from 'jordium-gantt-vue3'
1176
1274
 
1177
1275
  const toolbarConfig: ToolbarConfig = {
1178
- showAddTask: true, // 显示添加任务按钮
1179
- showAddMilestone: true, // 显示添加里程碑按钮
1180
- showTodayLocate: true, // 显示定位到今天按钮
1181
- showExportCsv: true, // 显示导出CSV按钮
1182
- showExportPdf: true, // 显示导出PDF按钮
1183
- showLanguage: true, // 显示语言切换按钮
1184
- showTheme: true, // 显示主题切换按钮
1185
- showFullscreen: true, // 显示全屏按钮
1186
- showTimeScale: true, // 显示时间刻度按钮组
1187
- timeScaleDimensions: [ // 显示所有时间刻度维度
1188
- 'hour', 'day', 'week', 'month', 'quarter', 'year'
1276
+ showAddTask: true, // 显示添加任务按钮
1277
+ showAddMilestone: true, // 显示添加里程碑按钮
1278
+ showTodayLocate: true, // 显示定位到今天按钮
1279
+ showExportCsv: true, // 显示导出CSV按钮
1280
+ showExportPdf: true, // 显示导出PDF按钮
1281
+ showLanguage: true, // 显示语言切换按钮
1282
+ showTheme: true, // 显示主题切换按钮
1283
+ showFullscreen: true, // 显示全屏按钮
1284
+ showTimeScale: true, // 显示时间刻度按钮组
1285
+ timeScaleDimensions: [
1286
+ // 显示所有时间刻度维度
1287
+ 'hour',
1288
+ 'day',
1289
+ 'week',
1290
+ 'month',
1291
+ 'quarter',
1292
+ 'year',
1189
1293
  ],
1190
- defaultTimeScale: 'week', // 默认选中周视图
1191
- showExpandCollapse: true // 显示展开/折叠按钮
1294
+ defaultTimeScale: 'week', // 默认选中周视图
1295
+ showExpandCollapse: true, // 显示展开/折叠按钮
1192
1296
  }
1193
1297
  </script>
1194
1298
  ```
@@ -1200,20 +1304,23 @@ const toolbarConfig: ToolbarConfig = {
1200
1304
  import type { ToolbarConfig } from 'jordium-gantt-vue3'
1201
1305
 
1202
1306
  const toolbarConfig: ToolbarConfig = {
1203
- showAddTask: true, // 保留添加任务
1204
- showAddMilestone: true, // 保留添加里程碑
1205
- showTodayLocate: true, // 保留定位今天
1206
- showExportCsv: false, // 隐藏导出CSV
1207
- showExportPdf: false, // 隐藏导出PDF
1208
- showLanguage: false, // 隐藏语言切换(固定使用一种语言)
1209
- showTheme: true, // 保留主题切换
1210
- showFullscreen: true, // 保留全屏
1211
- showTimeScale: true, // 显示时间刻度
1212
- timeScaleDimensions: [ // 只显示日/周/月三种刻度
1213
- 'day', 'week', 'month'
1307
+ showAddTask: true, // 保留添加任务
1308
+ showAddMilestone: true, // 保留添加里程碑
1309
+ showTodayLocate: true, // 保留定位今天
1310
+ showExportCsv: false, // 隐藏导出CSV
1311
+ showExportPdf: false, // 隐藏导出PDF
1312
+ showLanguage: false, // 隐藏语言切换(固定使用一种语言)
1313
+ showTheme: true, // 保留主题切换
1314
+ showFullscreen: true, // 保留全屏
1315
+ showTimeScale: true, // 显示时间刻度
1316
+ timeScaleDimensions: [
1317
+ // 只显示日/周/月三种刻度
1318
+ 'day',
1319
+ 'week',
1320
+ 'month',
1214
1321
  ],
1215
- defaultTimeScale: 'week', // 默认周视图
1216
- showExpandCollapse: true // 保留展开/折叠
1322
+ defaultTimeScale: 'week', // 默认周视图
1323
+ showExpandCollapse: true, // 保留展开/折叠
1217
1324
  }
1218
1325
  </script>
1219
1326
  ```
@@ -1231,9 +1338,9 @@ const toolbarConfig: ToolbarConfig = {
1231
1338
  TimelineScale.DAY,
1232
1339
  TimelineScale.WEEK,
1233
1340
  TimelineScale.MONTH,
1234
- TimelineScale.QUARTER
1341
+ TimelineScale.QUARTER,
1235
1342
  ],
1236
- defaultTimeScale: TimelineScale.MONTH // 默认月视图
1343
+ defaultTimeScale: TimelineScale.MONTH, // 默认月视图
1237
1344
  }
1238
1345
  </script>
1239
1346
  ```
@@ -1245,23 +1352,24 @@ const toolbarConfig: ToolbarConfig = {
1245
1352
  import type { ToolbarConfig } from 'jordium-gantt-vue3'
1246
1353
 
1247
1354
  const toolbarConfig: ToolbarConfig = {
1248
- showAddTask: false, // 隐藏所有编辑按钮
1355
+ showAddTask: false, // 隐藏所有编辑按钮
1249
1356
  showAddMilestone: false,
1250
- showTodayLocate: true, // 只保留导航功能
1357
+ showTodayLocate: true, // 只保留导航功能
1251
1358
  showExportCsv: false,
1252
1359
  showExportPdf: false,
1253
1360
  showLanguage: false,
1254
1361
  showTheme: false,
1255
1362
  showFullscreen: false,
1256
- showTimeScale: true, // 保留时间刻度切换
1363
+ showTimeScale: true, // 保留时间刻度切换
1257
1364
  timeScaleDimensions: ['week', 'month'],
1258
1365
  defaultTimeScale: 'month',
1259
- showExpandCollapse: false // 隐藏展开/折叠
1366
+ showExpandCollapse: false, // 隐藏展开/折叠
1260
1367
  }
1261
1368
  </script>
1262
1369
  ```
1263
1370
 
1264
1371
  > **💡 配置建议**:
1372
+ >
1265
1373
  > - **默认配置**:不传 `toolbar-config` 时,所有按钮默认显示
1266
1374
  > - **按需显示**:根据业务需求隐藏不需要的功能按钮
1267
1375
  > - **时间刻度**:`timeScaleDimensions` 控制显示哪些时间维度,建议选择 2-4 个常用维度
@@ -1273,32 +1381,29 @@ const toolbarConfig: ToolbarConfig = {
1273
1381
 
1274
1382
  **类型定义:**
1275
1383
 
1276
- | 字段名 | 类型 | 默认值 | 说明 |
1277
- |--------|------|--------|------|
1278
- | `columns` | `TaskListColumnConfig[]` | 默认8列 | 任务列表的列配置数组,定义显示哪些列及其属性 |
1279
- | `showAllColumns` | `boolean` | `true` | 是否显示所有列。`true` 时忽略 `columns` 中的 `visible` 设置 |
1280
- | `defaultWidth` | `number \| string` | `320` | 默认展开宽度。支持像素数字(如 `320`)或百分比字符串(如 `'30%'`) |
1281
- | `minWidth` | `number \| string` | `280` | 最小宽度。支持像素数字(如 `280`)或百分比字符串(如 `'20%'`)。不能小于 280px |
1282
- | `maxWidth` | `number \| string` | `1160` | 最大宽度。支持像素数字(如 `1160`)或百分比字符串(如 `'80%'`) |
1384
+ | 字段名 | 类型 | 默认值 | 说明 |
1385
+ | ---------------- | ------------------------ | ------- | ------------------------------------------------------------------------------ |
1386
+ | `columns` | `TaskListColumnConfig[]` | 默认8列 | 任务列表的列配置数组,定义显示哪些列及其属性 |
1387
+ | `showAllColumns` | `boolean` | `true` | 是否显示所有列。`true` 时忽略 `columns` 中的 `visible` 设置 |
1388
+ | `defaultWidth` | `number \| string` | `320` | 默认展开宽度。支持像素数字(如 `320`)或百分比字符串(如 `'30%'`) |
1389
+ | `minWidth` | `number \| string` | `280` | 最小宽度。支持像素数字(如 `280`)或百分比字符串(如 `'20%'`)。不能小于 280px |
1390
+ | `maxWidth` | `number \| string` | `1160` | 最大宽度。支持像素数字(如 `1160`)或百分比字符串(如 `'80%'`) |
1283
1391
 
1284
1392
  **TaskListColumnConfig 类型定义:**
1285
1393
 
1286
- | 字段名 | 类型 | 必填 | 说明 |
1287
- |--------|------|------|------|
1288
- | `key` | `string` | ✅ | 列的唯一标识符,用于访问 Task 对象中的字段,也用于国际化 |
1289
- | `label` | `string` | - | 列的显示标签(表头文字) |
1290
- | `cssClass` | `string` | - | 自定义 CSS 类名 |
1291
- | `width` | `number` | - | 列宽度(单位:像素) |
1292
- | `visible` | `boolean` | - | 是否显示该列,默认 `true`。当 `showAllColumns=true` 时此设置无效 |
1394
+ | 字段名 | 类型 | 必填 | 说明 |
1395
+ | ---------- | --------- | ---- | ---------------------------------------------------------------- |
1396
+ | `key` | `string` | ✅ | 列的唯一标识符,用于访问 Task 对象中的字段,也用于国际化 |
1397
+ | `label` | `string` | - | 列的显示标签(表头文字) |
1398
+ | `cssClass` | `string` | - | 自定义 CSS 类名 |
1399
+ | `width` | `number` | - | 列宽度(单位:像素) |
1400
+ | `visible` | `boolean` | - | 是否显示该列,默认 `true`。当 `showAllColumns=true` 时此设置无效 |
1293
1401
 
1294
1402
  **示例1:基础配置(调整宽度)**
1295
1403
 
1296
1404
  ```vue
1297
1405
  <template>
1298
- <GanttChart
1299
- :tasks="tasks"
1300
- :task-list-config="taskListConfig"
1301
- />
1406
+ <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
1302
1407
  </template>
1303
1408
 
1304
1409
  <script setup lang="ts">
@@ -1307,9 +1412,9 @@ import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
1307
1412
  import type { TaskListConfig } from 'jordium-gantt-vue3'
1308
1413
 
1309
1414
  const taskListConfig: TaskListConfig = {
1310
- defaultWidth: 450, // 默认宽度450px(比默认值320px更宽)
1311
- minWidth: 300, // 最小宽度300px
1312
- maxWidth: 1200, // 最大宽度1200px
1415
+ defaultWidth: 450, // 默认宽度450px(比默认值320px更宽)
1416
+ minWidth: 300, // 最小宽度300px
1417
+ maxWidth: 1200, // 最大宽度1200px
1313
1418
  }
1314
1419
  </script>
1315
1420
  ```
@@ -1318,10 +1423,7 @@ const taskListConfig: TaskListConfig = {
1318
1423
 
1319
1424
  ```vue
1320
1425
  <template>
1321
- <GanttChart
1322
- :tasks="tasks"
1323
- :task-list-config="taskListConfig"
1324
- />
1426
+ <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
1325
1427
  </template>
1326
1428
 
1327
1429
  <script setup lang="ts">
@@ -1330,9 +1432,9 @@ import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
1330
1432
  import type { TaskListConfig } from 'jordium-gantt-vue3'
1331
1433
 
1332
1434
  const taskListConfig: TaskListConfig = {
1333
- defaultWidth: '25%', // 默认占容器宽度的25%
1334
- minWidth: '15%', // 最小占15%
1335
- maxWidth: '60%', // 最大占60%
1435
+ defaultWidth: '25%', // 默认占容器宽度的25%
1436
+ minWidth: '15%', // 最小占15%
1437
+ maxWidth: '60%', // 最大占60%
1336
1438
  }
1337
1439
  </script>
1338
1440
  ```
@@ -1343,10 +1445,7 @@ const taskListConfig: TaskListConfig = {
1343
1445
 
1344
1446
  ```vue
1345
1447
  <template>
1346
- <GanttChart
1347
- :tasks="tasks"
1348
- :task-list-config="taskListConfig"
1349
- />
1448
+ <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
1350
1449
  </template>
1351
1450
 
1352
1451
  <script setup lang="ts">
@@ -1394,7 +1493,7 @@ const taskListConfig: TaskListConfig = {
1394
1493
  defaultWidth: 350,
1395
1494
  minWidth: 280,
1396
1495
  maxWidth: 500,
1397
- showAllColumns: false, // 只显示 visible=true 的列
1496
+ showAllColumns: false, // 只显示 visible=true 的列
1398
1497
  }
1399
1498
  </script>
1400
1499
  ```
@@ -1410,9 +1509,9 @@ import type { TaskListConfig, TaskListColumnConfig } from 'jordium-gantt-vue3'
1410
1509
  // 定义包含自定义列的配置
1411
1510
  const columns: TaskListColumnConfig[] = [
1412
1511
  { key: 'name', label: '任务名称', visible: true },
1413
- { key: 'priority', label: '优先级', width: 80, visible: true }, // 自定义列
1414
- { key: 'department', label: '部门', width: 100, visible: true }, // 自定义列
1415
- { key: 'status', label: '状态', width: 80, visible: true }, // 自定义列
1512
+ { key: 'priority', label: '优先级', width: 80, visible: true }, // 自定义列
1513
+ { key: 'department', label: '部门', width: 100, visible: true }, // 自定义列
1514
+ { key: 'status', label: '状态', width: 80, visible: true }, // 自定义列
1416
1515
  { key: 'assignee', label: '负责人', visible: true },
1417
1516
  { key: 'startDate', label: '开始日期', visible: true },
1418
1517
  { key: 'endDate', label: '结束日期', visible: true },
@@ -1431,10 +1530,7 @@ const taskListConfig: TaskListConfig = {
1431
1530
 
1432
1531
  ```vue
1433
1532
  <template>
1434
- <GanttChart
1435
- :tasks="tasks"
1436
- :task-list-config="taskListConfig"
1437
- />
1533
+ <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
1438
1534
  </template>
1439
1535
 
1440
1536
  <script setup lang="ts">
@@ -1473,6 +1569,7 @@ const taskListConfig = computed<TaskListConfig>(() => ({
1473
1569
  ```
1474
1570
 
1475
1571
  > **💡 配置说明**:
1572
+ >
1476
1573
  > - **默认行为**:不传 `task-list-config` 时,显示所有 8 个默认列,宽度为 320px
1477
1574
  > - **宽度单位**:支持像素(`number`)和百分比(`string`,如 `'30%'`)两种方式
1478
1575
  > - **百分比计算**:基于甘特图容器的总宽度,响应式调整
@@ -1488,17 +1585,18 @@ const taskListConfig = computed<TaskListConfig>(() => ({
1488
1585
 
1489
1586
  **配置字段:**
1490
1587
 
1491
- | 字段名 | 类型 | 默认值 | 说明 |
1492
- |--------|------|--------|------|
1493
- | `showAvatar` | `boolean` | `true` | 是否展示头像 |
1494
- | `showTitle` | `boolean` | `true` | 是否展示标题文字 |
1495
- | `showProgress` | `boolean` | `true` | 是否展示进度文字 |
1496
- | `dragThreshold` | `number` | `5` | 拖拽触发阈值(像素) |
1497
- | `resizeHandleWidth` | `number` | `5` | 拉伸手柄宽度(像素),最大 15px |
1498
- | `enableDragDelay` | `boolean` | `false` | 是否启用拖拽延迟(防止误触) |
1499
- | `dragDelayTime` | `number` | `150` | 拖拽延迟时间(毫秒) |
1588
+ | 字段名 | 类型 | 默认值 | 说明 |
1589
+ | ------------------- | --------- | ------- | ------------------------------- |
1590
+ | `showAvatar` | `boolean` | `true` | 是否展示头像 |
1591
+ | `showTitle` | `boolean` | `true` | 是否展示标题文字 |
1592
+ | `showProgress` | `boolean` | `true` | 是否展示进度文字 |
1593
+ | `dragThreshold` | `number` | `5` | 拖拽触发阈值(像素) |
1594
+ | `resizeHandleWidth` | `number` | `5` | 拉伸手柄宽度(像素),最大 15px |
1595
+ | `enableDragDelay` | `boolean` | `false` | 是否启用拖拽延迟(防止误触) |
1596
+ | `dragDelayTime` | `number` | `150` | 拖拽延迟时间(毫秒) |
1500
1597
 
1501
1598
  > **💡 编辑权限控制**:
1599
+ >
1502
1600
  > - **全局控制**:使用 `<GanttChart :allow-drag-and-resize="false" />` 禁用所有任务的拖拽/拉伸
1503
1601
  > - **单个任务控制**:设置任务对象的 `isEditable: false` 属性单独控制某个任务
1504
1602
 
@@ -1506,10 +1604,7 @@ const taskListConfig = computed<TaskListConfig>(() => ({
1506
1604
 
1507
1605
  ```vue
1508
1606
  <template>
1509
- <GanttChart
1510
- :tasks="tasks"
1511
- :task-bar-config="taskBarConfig"
1512
- />
1607
+ <GanttChart :tasks="tasks" :task-bar-config="taskBarConfig" />
1513
1608
  </template>
1514
1609
 
1515
1610
  <script setup lang="ts">
@@ -1535,10 +1630,7 @@ const taskBarConfig: TaskBarConfig = {
1535
1630
 
1536
1631
  ```vue
1537
1632
  <template>
1538
- <GanttChart
1539
- :tasks="tasks"
1540
- :allow-drag-and-resize="false"
1541
- />
1633
+ <GanttChart :tasks="tasks" :allow-drag-and-resize="false" />
1542
1634
  </template>
1543
1635
  ```
1544
1636
 
@@ -1612,6 +1704,7 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
1612
1704
  **核心设计思路:**
1613
1705
 
1614
1706
  1. **基础缓冲机制**:在任务的实际时间范围基础上,根据不同视图添加固定的缓冲区
1707
+
1615
1708
  - 小时视图:任务范围前后各 ±1 天
1616
1709
  - 日视图:任务范围前后各 ±30 天
1617
1710
  - 周视图:任务范围前后各 ±8 周(约2个月)
@@ -1620,10 +1713,12 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
1620
1713
  - 年视图:任务范围前后各 ±1 年
1621
1714
 
1622
1715
  2. **容器宽度适配**:基础缓冲后,如果计算出的时间线宽度小于容器宽度,会自动扩展范围
1716
+
1623
1717
  - 计算容器需要的时间单位数(天/周/月/季度/年)
1624
1718
  - 在基础范围两侧**对称扩展**,确保时间线填充满容器
1625
1719
 
1626
1720
  3. **空数据处理**:当没有任务数据时,根据容器宽度和时间刻度计算合理的时间范围
1721
+
1627
1722
  - 以当前日期为中心
1628
1723
  - 根据容器宽度动态计算需要显示的时间跨度
1629
1724
  - 确保最小显示范围(如日视图至少60天,周视图至少20周等)
@@ -1634,23 +1729,25 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
1634
1729
 
1635
1730
  **各视图计算模式对照表:**
1636
1731
 
1637
- | 视图 | 单位宽度 | 基础缓冲 | 空数据最小范围 | 容器自动填充? |
1638
- |------|----------|----------|----------------|----------|
1639
- | 小时视图 | 30px/时 | ±1天 | 3天 | ✅ |
1640
- | 日视图 | 30px/天 | ±30天 | 60天 | ✅ |
1641
- | 周视图 | 60px/周 | ±2月 | 20周 | ✅ |
1642
- | 月视图 | 60px/月 | ±1年 | 3年 | ✅ |
1643
- | 季度视图 | 60px/季度 (240px/年) | ±1年 | 5年 | ✅ |
1644
- | 年视图 | 360px/年 | ±1年 | 5年 | ✅ |
1732
+ | 视图 | 单位宽度 | 基础缓冲 | 空数据最小范围 | 容器自动填充? |
1733
+ | -------- | -------------------- | -------- | -------------- | -------------- |
1734
+ | 小时视图 | 30px/时 | ±1天 | 3天 | ✅ |
1735
+ | 日视图 | 30px/天 | ±30天 | 60天 | ✅ |
1736
+ | 周视图 | 60px/周 | ±2月 | 20周 | ✅ |
1737
+ | 月视图 | 60px/月 | ±1年 | 3年 | ✅ |
1738
+ | 季度视图 | 60px/季度 (240px/年) | ±1年 | 5年 | ✅ |
1739
+ | 年视图 | 360px/年 | ±1年 | 5年 | ✅ |
1645
1740
 
1646
1741
  **实际应用场景:**
1647
1742
 
1648
1743
  - **短期任务**(如1周项目, 分辨率1080):
1744
+
1649
1745
  - 不会导致时间线过窄,自动扩展到填充满容器
1650
1746
  - 日视图:1周(7天×30px=210px) → 扩展至 ≥1200px(约40天)
1651
1747
  - 周视图:1周(60px) → 扩展至 ≥1200px(约20周)
1652
1748
 
1653
1749
  - **长期项目**(如2年项目):
1750
+
1654
1751
  - 添加固定缓冲后,自动适配容器
1655
1752
  - 月视图:24个月 + 缓冲 → 如需要则扩展至容器宽度
1656
1753
  - 季度视图:8个季度 + 缓冲 → 如需要则扩展至容器宽度
@@ -1662,6 +1759,7 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
1662
1759
  - 季度/年视图:显示至少5年
1663
1760
 
1664
1761
  > **💡 自动化优势**:
1762
+ >
1665
1763
  > - 无需手动设置 `startDate` 和 `endDate`,组件会自动计算最优范围
1666
1764
  > - 响应式容器宽度变化,时间线自动重新计算
1667
1765
  > - 不同视图独立优化,切换视图时自动调整到最佳显示效果
@@ -1676,10 +1774,7 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
1676
1774
 
1677
1775
  ```vue
1678
1776
  <template>
1679
- <GanttChart
1680
- :tasks="tasks"
1681
- :on-theme-change="handleThemeChange"
1682
- />
1777
+ <GanttChart :tasks="tasks" :on-theme-change="handleThemeChange" />
1683
1778
  </template>
1684
1779
 
1685
1780
  <script setup lang="ts">
@@ -1703,21 +1798,21 @@ const handleThemeChange = (isDark: boolean) => {
1703
1798
  --gantt-success-color: #67c23a;
1704
1799
  --gantt-warning-color: #e6a23c;
1705
1800
  --gantt-danger-color: #f56c6c;
1706
-
1801
+
1707
1802
  /* 背景色 */
1708
1803
  --gantt-bg-primary: #ffffff;
1709
1804
  --gantt-bg-secondary: #f5f7fa;
1710
1805
  --gantt-bg-hover: #ecf5ff;
1711
-
1806
+
1712
1807
  /* 文字颜色 */
1713
1808
  --gantt-text-primary: #303133;
1714
1809
  --gantt-text-secondary: #606266;
1715
1810
  --gantt-text-placeholder: #c0c4cc;
1716
-
1811
+
1717
1812
  /* 边框颜色 */
1718
1813
  --gantt-border-color: #dcdfe6;
1719
1814
  --gantt-border-color-light: #e4e7ed;
1720
-
1815
+
1721
1816
  /* 任务条颜色 */
1722
1817
  --gantt-task-bg: #409eff;
1723
1818
  --gantt-task-border: #66b1ff;
@@ -1729,13 +1824,13 @@ const handleThemeChange = (isDark: boolean) => {
1729
1824
  --gantt-bg-primary: #1a1a1a;
1730
1825
  --gantt-bg-secondary: #2c2c2c;
1731
1826
  --gantt-bg-hover: #3a3a3a;
1732
-
1827
+
1733
1828
  --gantt-text-primary: #e5e5e5;
1734
1829
  --gantt-text-secondary: #b0b0b0;
1735
-
1830
+
1736
1831
  --gantt-border-color: #3a3a3a;
1737
1832
  --gantt-border-color-light: #4a4a4a;
1738
-
1833
+
1739
1834
  --gantt-task-bg: #409eff;
1740
1835
  --gantt-task-border: #66b1ff;
1741
1836
  --gantt-task-text: #ffffff;
@@ -1748,10 +1843,7 @@ const handleThemeChange = (isDark: boolean) => {
1748
1843
 
1749
1844
  ```vue
1750
1845
  <template>
1751
- <GanttChart
1752
- :tasks="tasks"
1753
- :on-language-change="handleLanguageChange"
1754
- />
1846
+ <GanttChart :tasks="tasks" :on-language-change="handleLanguageChange" />
1755
1847
  </template>
1756
1848
 
1757
1849
  <script setup lang="ts">
@@ -1769,66 +1861,67 @@ const handleLanguageChange = (lang: 'zh-CN' | 'en-US') => {
1769
1861
 
1770
1862
  ```vue
1771
1863
  <template>
1772
- <GanttChart
1773
- :tasks="tasks"
1774
- :locale-messages="customMessages"
1775
- />
1864
+ <GanttChart :tasks="tasks" :locale-messages="customMessages" />
1776
1865
  </template>
1777
1866
 
1778
1867
  <script setup lang="ts">
1779
1868
  const customMessages = {
1780
- // 任务列表相关
1781
- name: '任务名称(自定义)',
1782
- startDate: '开始日期',
1783
- endDate: '结束日期',
1784
- duration: '工期',
1785
- progress: '完成度',
1786
- predecessor: '前置任务',
1787
- assignee: '负责人',
1788
- estimatedHours: '预估工时',
1789
- actualHours: '实际工时'
1790
-
1791
- // 工具栏相关
1792
- addTask: '新建任务',
1793
- addMilestone: '新建里程碑',
1794
- today: '今天',
1795
- exportCsv: '导出 CSV',
1796
- exportPdf: '导出 PDF',
1797
- fullscreen: '全屏',
1798
- exitFullscreen: '退出全屏',
1799
- language: '语言',
1800
- theme: '主题',
1801
- expandAll: '全部展开',
1802
- collapseAll: '全部折叠'
1803
-
1804
- // 内置任务编辑器相关
1805
- title: '任务详情',
1806
- titleEdit: '编辑任务',
1807
- titleNew: '新建任务',
1808
- name: '任务名称',
1809
- startDate: '开始日期',
1810
- endDate: '结束日期',
1811
- assignee: '负责人',
1812
- predecessor: '前置任务',
1813
- description: '描述',
1814
- estimatedHours: '预估工时',
1815
- actualHours: '实际工时',
1816
- progress: '进度',
1817
- save: '保存',
1818
- cancel: '取消',
1819
- delete: '删除'
1820
-
1821
- // 其他文本
1822
- days: '天',
1823
- hours: '小时',
1824
- overtime: '超时',
1825
- overdue: '逾期',
1826
- // ... 更多自定义翻译
1869
+ "zh-CN": {
1870
+ // 任务列表相关
1871
+ name: '任务名称(自定义)',
1872
+ startDate: '开始日期',
1873
+ endDate: '结束日期',
1874
+ duration: '工期',
1875
+ progress: '完成度',
1876
+ predecessor: '前置任务',
1877
+ assignee: '负责人',
1878
+ estimatedHours: '预估工时',
1879
+ actualHours: '实际工时'
1880
+
1881
+ // 工具栏相关
1882
+ addTask: '新建任务',
1883
+ addMilestone: '新建里程碑',
1884
+ today: '今天',
1885
+ exportCsv: '导出 CSV',
1886
+ exportPdf: '导出 PDF',
1887
+ fullscreen: '全屏',
1888
+ exitFullscreen: '退出全屏',
1889
+ language: '语言',
1890
+ theme: '主题',
1891
+ expandAll: '全部展开',
1892
+ collapseAll: '全部折叠'
1893
+
1894
+ // 内置任务编辑器相关
1895
+ title: '任务详情',
1896
+ titleEdit: '编辑任务',
1897
+ titleNew: '新建任务',
1898
+ name: '任务名称',
1899
+ startDate: '开始日期',
1900
+ endDate: '结束日期',
1901
+ assignee: '负责人',
1902
+ predecessor: '前置任务',
1903
+ description: '描述',
1904
+ estimatedHours: '预估工时',
1905
+ actualHours: '实际工时',
1906
+ progress: '进度',
1907
+ save: '保存',
1908
+ cancel: '取消',
1909
+ delete: '删除'
1910
+
1911
+ // 其他文本
1912
+ days: '',
1913
+ hours: '小时',
1914
+ overtime: '超时',
1915
+ overdue: '逾期',
1916
+ // ... 更多自定义翻译
1917
+ },
1918
+ "en-US": {......}
1827
1919
  }
1828
1920
  </script>
1829
1921
  ```
1830
1922
 
1831
1923
  > **💡 提示**:
1924
+ >
1832
1925
  > - `localeMessages` 采用**深度合并**策略,只需传递需要覆盖的字段即可
1833
1926
  > - 支持嵌套对象,如 `taskList.name`、`toolbar.addTask` 等
1834
1927
  > - 完整的翻译键请参考组件内置的 `messages['zh-CN']` 对象
@@ -1845,44 +1938,44 @@ const customMessages = {
1845
1938
 
1846
1939
  **插槽参数:**
1847
1940
 
1848
- | 参数名 | 类型 | 来源 | 说明 |
1849
- |--------|------|------|------|
1941
+ | 参数名 | 类型 | 来源 | 说明 |
1942
+ | ------ | ---------------------------- | ---- | ---------------- |
1850
1943
  | `type` | `'task-row'` \| `'task-bar'` | 通用 | 插槽调用位置标识 |
1851
- | `task` | `Task` | 通用 | 当前任务对象 |
1944
+ | `task` | `Task` | 通用 | 当前任务对象 |
1852
1945
 
1853
1946
  **TaskRow 特有参数(当 `type === 'task-row'` 时):**
1854
1947
 
1855
- | 参数名 | 类型 | 说明 |
1856
- |--------|------|------|
1857
- | `isRowContent` | `boolean` | 标识为行内容 |
1858
- | `level` | `number` | 任务层级 |
1859
- | `indent` | `string` | 缩进样式 |
1860
- | `isHovered` | `boolean` | 是否悬停 |
1861
- | `hoveredTaskId` | `number \| null` | 当前悬停任务ID |
1862
- | `isParent` | `boolean` | 是否为父任务 |
1863
- | `hasChildren` | `boolean` | 是否有子任务 |
1864
- | `collapsed` | `boolean` | 是否折叠 |
1865
- | `formattedTimer` | `string` | 格式化的计时文本 |
1866
- | `timerRunning` | `boolean` | 计时器是否运行 |
1867
- | `timerElapsed` | `number` | 已计时时长 |
1868
- | `isOvertime` | `number \| boolean \| undefined` | 是否超时 |
1869
- | `overdueDays` | `number` | 逾期天数 |
1870
- | `overtimeText` | `string` | 超时文本 |
1871
- | `overdueText` | `string` | 逾期文本 |
1872
- | `daysText` | `string` | 天数文本 |
1873
- | `progressClass` | `string` | 进度CSS类名 |
1948
+ | 参数名 | 类型 | 说明 |
1949
+ | ---------------- | -------------------------------- | ---------------- |
1950
+ | `isRowContent` | `boolean` | 标识为行内容 |
1951
+ | `level` | `number` | 任务层级 |
1952
+ | `indent` | `string` | 缩进样式 |
1953
+ | `isHovered` | `boolean` | 是否悬停 |
1954
+ | `hoveredTaskId` | `number \| null` | 当前悬停任务ID |
1955
+ | `isParent` | `boolean` | 是否为父任务 |
1956
+ | `hasChildren` | `boolean` | 是否有子任务 |
1957
+ | `collapsed` | `boolean` | 是否折叠 |
1958
+ | `formattedTimer` | `string` | 格式化的计时文本 |
1959
+ | `timerRunning` | `boolean` | 计时器是否运行 |
1960
+ | `timerElapsed` | `number` | 已计时时长 |
1961
+ | `isOvertime` | `number \| boolean \| undefined` | 是否超时 |
1962
+ | `overdueDays` | `number` | 逾期天数 |
1963
+ | `overtimeText` | `string` | 超时文本 |
1964
+ | `overdueText` | `string` | 逾期文本 |
1965
+ | `daysText` | `string` | 天数文本 |
1966
+ | `progressClass` | `string` | 进度CSS类名 |
1874
1967
 
1875
1968
  **TaskBar 特有参数(当 `type === 'task-bar'` 时):**
1876
1969
 
1877
- | 参数名 | 类型 | 说明 |
1878
- |--------|------|------|
1879
- | `status` | `object` | 任务状态对象,包含 `type`, `color`, `bgColor`, `borderColor` |
1880
- | `statusType` | `string` | 状态类型:`'completed'`, `'delayed'`, `'in-progress'`, `'not-started'`, `'parent'` |
1881
- | `isParent` | `boolean` | 是否为父任务 |
1882
- | `progress` | `number` | 任务进度(0-100) |
1883
- | `currentTimeScale` | `TimelineScale` | 当前时间刻度 |
1884
- | `rowHeight` | `number` | 行高(像素) |
1885
- | `dayWidth` | `number` | 每天宽度(像素) |
1970
+ | 参数名 | 类型 | 说明 |
1971
+ | ------------------ | --------------- | ---------------------------------------------------------------------------------- |
1972
+ | `status` | `object` | 任务状态对象,包含 `type`, `color`, `bgColor`, `borderColor` |
1973
+ | `statusType` | `string` | 状态类型:`'completed'`, `'delayed'`, `'in-progress'`, `'not-started'`, `'parent'` |
1974
+ | `isParent` | `boolean` | 是否为父任务 |
1975
+ | `progress` | `number` | 任务进度(0-100) |
1976
+ | `currentTimeScale` | `TimelineScale` | 当前时间刻度 |
1977
+ | `rowHeight` | `number` | 行高(像素) |
1978
+ | `dayWidth` | `number` | 每天宽度(像素) |
1886
1979
 
1887
1980
  **使用示例:**
1888
1981
 
@@ -1891,11 +1984,7 @@ const customMessages = {
1891
1984
  <GanttChart :tasks="tasks">
1892
1985
  <template #custom-task-content="slotProps">
1893
1986
  <!-- 根据类型渲染不同内容 -->
1894
- <CustomTaskContent
1895
- :task="slotProps.task"
1896
- :type="slotProps.type"
1897
- :status="slotProps.status"
1898
- />
1987
+ <CustomTaskContent :task="slotProps.task" :type="slotProps.type" :status="slotProps.status" />
1899
1988
  </template>
1900
1989
  </GanttChart>
1901
1990
  </template>
@@ -1913,8 +2002,8 @@ const tasks = ref<Task[]>([
1913
2002
  name: '<strong>重要任务</strong>',
1914
2003
  startDate: '2025-01-01',
1915
2004
  endDate: '2025-01-10',
1916
- progress: 50
1917
- }
2005
+ progress: 50,
2006
+ },
1918
2007
  ])
1919
2008
  </script>
1920
2009
  ```
@@ -1946,7 +2035,7 @@ const props = defineProps<Props>()
1946
2035
  <div v-if="type === 'task-row'" class="task-row-content">
1947
2036
  <span v-html="task.name" />
1948
2037
  </div>
1949
-
2038
+
1950
2039
  <!-- TaskBar 中的渲染 -->
1951
2040
  <div v-else-if="type === 'task-bar'" class="task-bar-content">
1952
2041
  <div class="task-icon" :style="{ color: status?.color }">📌</div>
@@ -1991,6 +2080,7 @@ const props = defineProps<Props>()
1991
2080
  ```
1992
2081
 
1993
2082
  > **💡 使用场景**:
2083
+ >
1994
2084
  > - 支持 HTML 格式的任务名称
1995
2085
  > - 添加自定义图标、标签或徽章
1996
2086
  > - 根据任务状态显示不同样式
@@ -1998,6 +2088,7 @@ const props = defineProps<Props>()
1998
2088
  > - 显示额外的业务信息
1999
2089
 
2000
2090
  > **⚠️ 注意事项**:
2091
+ >
2001
2092
  > - 插槽内容会同时在 TaskRow 和 TaskBar 中渲染
2002
2093
  > - 需要根据 `type` 参数区分渲染位置
2003
2094
  > - TaskRow 和 TaskBar 的可用空间不同,需要适配布局