jordium-gantt-vue3 1.4.4 → 1.4.6

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
@@ -23,7 +23,7 @@
23
23
 
24
24
  <p align="center">
25
25
  <a href="./README.md">中文</a> |
26
- <a href="./README-EN.md">English</a>
26
+ <a href="./README-EN.md">English</a> |
27
27
  <a href="./CHANGELOG.md">更新日志</a>
28
28
  </p>
29
29
 
@@ -179,16 +179,17 @@ npm run dev
179
179
 
180
180
  #### 基础属性
181
181
 
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 |
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 |
192
+ | `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | 任务编辑抽屉中负责人下拉菜单的选项列表 |
192
193
 
193
194
  #### 配置对象属性
194
195
 
@@ -243,14 +244,14 @@ npm run dev
243
244
  | `milestone-deleted` | `{ milestoneId: number }` | 里程碑删除 |
244
245
  | `milestone-icon-changed` | `{ milestoneId, icon }` | 里程碑图标变更 |
245
246
  | `milestone-drag-end` | `(milestone: Task)` | 拖拽里程碑结束 |
246
- | `task-row-moved` | `payload: { draggedTask: Task targetTask: Taskposition: 'after' 'child'}` | 拖拽TaskRow结束 |
247
+ | `task-row-moved` | `payload: { draggedTask: Task, targetTask: Task, position: 'after' \| 'child', oldParent: Task \| null, newParent: Task \| null }` | 拖拽TaskRow结束(可选) |
247
248
 
248
249
  #### 示例1:最简单的甘特图
249
250
 
250
251
  ```vue
251
252
  <template>
252
253
  <div style="height: 600px;">
253
- <GanttChart :tasks="tasks" />
254
+ <GanttChart :tasks="tasks" :assignee-options="assigneeOptions" />
254
255
  </div>
255
256
  </template>
256
257
 
@@ -268,6 +269,12 @@ const tasks = ref([
268
269
  progress: 100,
269
270
  },
270
271
  ])
272
+
273
+ const assigneeOptions = ref([
274
+ { value: 'zhangsan', label: '张三' },
275
+ { value: 'lisi', label: '李四' },
276
+ { value: 'wangwu', label: '王五' },
277
+ ])
271
278
  </script>
272
279
  ```
273
280
 
@@ -276,7 +283,7 @@ const tasks = ref([
276
283
  ```vue
277
284
  <template>
278
285
  <div style="height: 600px;">
279
- <GanttChart :tasks="tasks" :milestones="milestones" />
286
+ <GanttChart :tasks="tasks" :milestones="milestones" :assignee-options="assigneeOptions" />
280
287
  </div>
281
288
  </template>
282
289
 
@@ -304,6 +311,12 @@ const milestones = ref([
304
311
  icon: 'diamond',
305
312
  },
306
313
  ])
314
+
315
+ const assigneeOptions = ref([
316
+ { value: 'zhangsan', label: '张三' },
317
+ { value: 'lisi', label: '李四' },
318
+ { value: 'wangwu', label: '王五' },
319
+ ])
307
320
  </script>
308
321
  ```
309
322
 
@@ -324,6 +337,7 @@ const milestones = ref([
324
337
  :tasks="tasks"
325
338
  :milestones="milestones"
326
339
  :show-toolbar="false"
340
+ :assignee-options="assigneeOptions"
327
341
  @task-added="handleTaskAdded"
328
342
  @milestone-saved="handleMilestoneSaved"
329
343
  />
@@ -339,6 +353,12 @@ import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
339
353
  const tasks = ref([])
340
354
  const milestones = ref([])
341
355
 
356
+ const assigneeOptions = ref([
357
+ { value: 'zhangsan', label: '张三' },
358
+ { value: 'lisi', label: '李四' },
359
+ { value: 'wangwu', label: '王五' },
360
+ ])
361
+
342
362
  const addTask = () => {
343
363
  const newTask = {
344
364
  id: Date.now(),
@@ -386,7 +406,8 @@ const handleMilestoneSaved = milestone => {
386
406
  | `endDate` | `string` | - | - | 结束日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
387
407
  | `progress` | `number` | - | `0` | 任务进度,范围 0-100 |
388
408
  | `predecessor` | `number[]` | - | - | 前置任务 ID 数组,标准格式:`[1, 2, 3]`<br/>**兼容格式**:也支持字符串 `'1,2,3'` 或字符串数组 `['1', '2', '3']`,组件会自动解析 |
389
- | `assignee` | `string` | - | - | 任务负责人 |
409
+ | `assignee` | `string` | - | - | 任务负责人,用作负责人下拉菜单的值绑定 |
410
+ | `assigneeName` | `string` | - | - | 任务负责人姓名,自动从绑定的数据集`assigneeOptions`中获取Label作为显示,如果需要自定义,可以在GanttChart回调事件`task-added`中自定义信息 |
390
411
  | `avatar` | `string` | - | - | 任务负责人头像 URL |
391
412
  | `estimatedHours` | `number` | - | - | 预估工时(小时) |
392
413
  | `actualHours` | `number` | - | - | 实际工时(小时) |
@@ -425,7 +446,8 @@ const handleMilestoneSaved = milestone => {
425
446
  | `taskBarConfig` | `TaskBarConfig` | `{}` | 任务条样式配置,详见 [TaskBarConfig 配置](#taskbarconfig-配置) |
426
447
  | `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置,详见 [TaskListConfig 配置](#tasklistconfig-配置) |
427
448
  | `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
428
- | `enableTaskRowMove` | `boolean` | `false` | 是否允许拖拽和摆放TaskRow
449
+ | `enableTaskRowMove` | `boolean` | `false` | 是否允许拖拽和摆放TaskRow |
450
+ | `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | 任务编辑抽屉中负责人下拉菜单的选项列表 |
429
451
 
430
452
  **配置说明**:
431
453
 
@@ -451,7 +473,7 @@ const handleMilestoneSaved = milestone => {
451
473
  | `successor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加后置任务后 | `targetTask` 是原任务,`newTask` 是新创建的后置任务(其 predecessor 已包含 targetTask.id) |
452
474
  | `timer-started` | `(task: Task) => void` | 任务计时器启动时 | 开始记录任务工时 |
453
475
  | `timer-stopped` | `(task: Task) => void` | 任务计时器停止时 | 停止记录任务工时 |
454
- | `task-row-moved` | `payload: { draggedTask: Task targetTask: Taskposition: 'after' 'child'}` | 拖拽TaskRow结束 | TaskList中的TasRow按住拖拽,完成前后排放位置放置后
476
+ | `task-row-moved` | `payload: { draggedTask: Task, targetTask: Task, position: 'after' \| 'child', oldParent: Task \| null, newParent: Task \| null }` | 拖拽TaskRow结束(可选) | 组件已自动完成数据移动和TaskList/Timeline同步。监听此事件为完全可选,仅用于显示提示、调用API保存等。`position`: 'after'=同级放置,'child'=作为子任务 |
455
477
 
456
478
  **数据同步说明**:
457
479
 
@@ -466,6 +488,7 @@ const handleMilestoneSaved = milestone => {
466
488
  <div style="height: 600px;">
467
489
  <GanttChart
468
490
  :tasks="tasks"
491
+ :assignee-options="assigneeOptions"
469
492
  @add-task="handleAddTask"
470
493
  @task-added="handleTaskAdded"
471
494
  @task-updated="handleTaskUpdated"
@@ -503,6 +526,12 @@ const tasks = ref<Task[]>([
503
526
  },
504
527
  ])
505
528
 
529
+ const assigneeOptions = ref([
530
+ { value: 'zhangsan', label: '张三' },
531
+ { value: 'lisi', label: '李四' },
532
+ { value: 'wangwu', label: '王五' },
533
+ ])
534
+
506
535
  // 工具栏"添加任务"按钮点击事件
507
536
  const handleAddTask = () => {
508
537
  console.log('准备新增任务...')
@@ -555,6 +584,7 @@ const handleTaskDragEnd = (task: Task) => {
555
584
  <template>
556
585
  <GanttChart
557
586
  :tasks="tasks"
587
+ :assignee-options="assigneeOptions"
558
588
  @predecessor-added="handlePredecessorAdded"
559
589
  @successor-added="handleSuccessorAdded"
560
590
  />
@@ -617,6 +647,12 @@ const tasks = ref<Task[]>([
617
647
  },
618
648
  ])
619
649
 
650
+ const assigneeOptions = ref([
651
+ { value: 'zhangsan', label: '张三' },
652
+ { value: 'lisi', label: '李四' },
653
+ { value: 'wangwu', label: '王五' },
654
+ ])
655
+
620
656
  // 通过右键菜单添加前置任务时触发
621
657
  const handlePredecessorAdded = (event: { targetTask: Task; newTask: Task }) => {
622
658
  console.log(`任务 [${event.targetTask.name}] 添加了前置任务 [${event.newTask.name}]`)
@@ -670,6 +706,7 @@ const handleSuccessorAdded = (event: { targetTask: Task; newTask: Task }) => {
670
706
  :show-toolbar="false"
671
707
  :use-default-drawer="true"
672
708
  :use-default-milestone-dialog="true"
709
+ :assignee-options="assigneeOptions"
673
710
  @add-task="handleAddTask"
674
711
  @add-milestone="handleAddMilestone"
675
712
  @task-added="handleTaskAdded"
@@ -685,6 +722,12 @@ import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
685
722
  const tasks = ref([])
686
723
  const milestones = ref([])
687
724
 
725
+ const assigneeOptions = ref([
726
+ { value: 'zhangsan', label: '张三' },
727
+ { value: 'lisi', label: '李四' },
728
+ { value: 'wangwu', label: '王五' },
729
+ ])
730
+
688
731
  // 自定义按钮触发事件(组件会响应并打开内置编辑器)
689
732
  const triggerAddTask = () => {
690
733
  // 直接触发组件的 add-task 事件
@@ -728,6 +771,7 @@ const handleTaskAdded = e => {
728
771
  <GanttChart
729
772
  :tasks="tasks"
730
773
  :enable-task-row-move="true"
774
+ :assignee-options="assigneeOptions"
731
775
  @task-row-moved="handleTaskRowMoved"
732
776
  />
733
777
  </div>
@@ -764,31 +808,47 @@ const tasks = ref<Task[]>([
764
808
  },
765
809
  ])
766
810
 
767
- // 任务行拖拽完成事件
768
- const handleTaskRowMoved = (payload: {
811
+ const assigneeOptions = ref([
812
+ { value: 'zhangsan', label: '张三' },
813
+ { value: 'lisi', label: '李四' },
814
+ { value: 'wangwu', label: '王五' },
815
+ ])
816
+
817
+ // 任务行拖拽完成事件(可选)
818
+ const handleTaskRowMoved = async (payload: {
769
819
  draggedTask: Task
770
820
  targetTask: Task
771
821
  position: 'after' | 'child'
822
+ oldParent: Task | null
823
+ newParent: Task | null
772
824
  }) => {
773
- const { draggedTask, targetTask, position } = payload
825
+ const { draggedTask, targetTask, position, oldParent, newParent } = payload
774
826
 
775
- console.log(`任务 [${draggedTask.name}] 被拖拽到任务 [${targetTask.name}] ${position === 'after' ? '之后' : '下方作为子任务'}`)
827
+ // 组件已自动完成任务移动、parentId更新和TaskList/Timeline同步
828
+ // 监听此事件为完全可选,仅用于:
776
829
 
777
- // 组件已自动更新任务的层级关系和位置
778
- // position === 'after': 任务被放置在目标任务之后(同级)
779
- // position === 'child': 任务被放置为目标任务的子任务(第一个子任务位置)
830
+ // 1. 显示自定义提示消息
831
+ const oldParentName = oldParent?.name || '根目录'
832
+ const newParentName = newParent?.name || '根目录'
833
+ const positionText = position === 'after' ? '在目标任务之后' : '作为目标任务的子任务'
834
+ showMessage(`任务 [${draggedTask.name}] 已从 [${oldParentName}] 移动到 [${newParentName}] (${positionText})`, 'success')
780
835
 
781
- // 这里可以:
782
- // 1. 显示确认对话框,让用户确认是否移动
783
836
  // 2. 调用后端 API 保存新的任务层级关系
784
- // 3. 更新相关的依赖关系
837
+ try {
838
+ await api.updateTaskHierarchy({
839
+ taskId: draggedTask.id,
840
+ targetTaskId: targetTask.id,
841
+ position: position,
842
+ oldParentId: oldParent?.id,
843
+ newParentId: newParent?.id,
844
+ })
845
+ } catch (error) {
846
+ console.error('保存任务层级失败:', error)
847
+ showMessage('保存失败,请刷新页面', 'error')
848
+ }
785
849
 
786
- // 示例:调用后端 API
787
- // await api.updateTaskHierarchy({
788
- // taskId: draggedTask.id,
789
- // targetTaskId: targetTask.id,
790
- // position: position
791
- // })
850
+ // 3. 触发其他业务逻辑(如更新关联数据、记录操作日志等)
851
+ // ...
792
852
  }
793
853
  </script>
794
854
  ```
@@ -796,7 +856,7 @@ const handleTaskRowMoved = (payload: {
796
856
  **拖拽排序说明**:
797
857
 
798
858
  - **启用拖拽**:设置 `enable-task-row-move="true"` 启用任务行拖拽功能(默认为 `false`)
799
- - **拖拽算法**:
859
+ - **拖拽算法**(组件内部自动执行):
800
860
  - **算法1(放置在后面)**:当目标任务没有子任务时,被拖拽的任务会放置在目标任务之后(同级),`position='after'`
801
861
  - **算法2(作为子任务)**:当目标任务有子任务时,被拖拽的任务会成为目标任务的第一个子任务,`position='child'`
802
862
  - **视觉反馈**:
@@ -804,7 +864,16 @@ const handleTaskRowMoved = (payload: {
804
864
  - 悬停在有效目标任务上时显示蓝色边框提示
805
865
  - 无子任务的任务显示蓝色底部边框
806
866
  - 有子任务的任务显示蓝色四周边框
807
- - **自动更新**:组件会自动更新任务的 `parentId` 字段和 `children` 数组,外部只需监听事件做额外处理(如保存到后端)
867
+ - **自动同步**:组件内部通过对象引用直接修改 `props.tasks`,自动完成任务移动、`parentId` 更新、`children` 数组调整以及 TaskList/Timeline 同步
868
+ - **事件监听(可选)**:
869
+ - `task-row-moved` 事件为完全可选,仅用于显示提示、调用API保存、记录日志等额外处理
870
+ - 无需手动更新 `tasks.value`,组件已自动完成数据同步
871
+ - **事件参数**:
872
+ - `draggedTask`: 被拖拽的任务
873
+ - `targetTask`: 目标任务
874
+ - `position`: 放置位置('after' 或 'child')
875
+ - `oldParent`: 原父任务(null 表示根目录)
876
+ - `newParent`: 新父任务(null 表示根目录)
808
877
  - **限制条件**:
809
878
  - 不能拖拽到自己身上
810
879
  - 不能拖拽到自己的子任务上(避免循环引用)
@@ -1221,6 +1290,54 @@ const handleDelete = () => {
1221
1290
 
1222
1291
  本章节详细介绍 GanttChart 组件的配置选项和扩展能力,包括组件配置、主题与国际化、自定义扩展三个部分。
1223
1292
 
1293
+ ### 任务类型定义
1294
+
1295
+ 任务类型(`type` 字段)用于区分不同类型的任务,组件内部会根据类型执行不同的逻辑判断。
1296
+
1297
+ #### 内置任务类型
1298
+
1299
+ | 类型值 | 说明 | 默认值 |
1300
+ | ------- | ---------- | ------ |
1301
+ | `story` | 用户故事 | - |
1302
+ | `task` | 普通任务 | ✅ |
1303
+ | `bug` | 缺陷/问题 | - |
1304
+
1305
+ #### 功能区分
1306
+
1307
+ 不同任务类型在组件中具有不同的功能特性:
1308
+
1309
+ | 功能 | story | task | bug |
1310
+ | ---------------- | ----- | ---- | --- |
1311
+ | 可作为上级任务 | ✅ | ✅ | ❌ |
1312
+ | 可作为前置任务 | ❌ | ✅ | ❌ |
1313
+ | 支持计时器 | ❌ | ✅ | ✅ |
1314
+ | 自动视为父任务 | ✅ | ❌ | ❌ |
1315
+ | 删除时特殊提示 | ✅ | ❌ | ❌ |
1316
+
1317
+ #### 注意事项
1318
+
1319
+ > ⚠️ **重要提示**
1320
+ >
1321
+ > 1. 任务类型值为组件内置判断使用,**请勿随意修改**这些枚举值
1322
+ > 2. 客制化 TaskDrawer 时,必须保持 `story`、`task`、`bug` 这三个枚举值
1323
+ > 3. 如需添加其他业务标签,建议使用自定义属性字段,例如:`customType`、`category`、`label` 等
1324
+
1325
+ **示例:使用自定义标签**
1326
+
1327
+ ```typescript
1328
+ const tasks = ref([
1329
+ {
1330
+ id: 1,
1331
+ name: '需求分析',
1332
+ type: 'task', // 保持组件内置类型
1333
+ customType: 'requirement', // 自定义业务类型
1334
+ category: 'analysis', // 自定义分类
1335
+ startDate: '2025-01-01',
1336
+ endDate: '2025-01-10',
1337
+ },
1338
+ ])
1339
+ ```
1340
+
1224
1341
  ### 组件配置
1225
1342
 
1226
1343
  #### ToolbarConfig(工具栏配置)
@@ -2172,5 +2289,5 @@ jordium-gantt-vue3/
2172
2289
  ---
2173
2290
 
2174
2291
  <p align="center">
2175
- <sub>如果这个项目对你有帮助,请给一个 ⭐️ 支持一下!</sub>
2292
+ 如果这个项目对你有帮助,请给一个 ⭐️ 支持一下!
2176
2293
  </p>