diff --git a/README-EN.md b/README-EN.md index ef96aa9..f5438af 100644 --- a/README-EN.md +++ b/README-EN.md @@ -2,7 +2,10 @@
-
+
+
+
+
@@ -105,10 +108,7 @@ Create your first Gantt chart:
```vue
**Compatible formats**: Also supports string `'1,2,3'` or string array `['1', '2', '3']`, component will auto-parse |
-| `assignee` | `string` | - | - | Task assignee |
-| `avatar` | `string` | - | - | Avatar URL of task assignee |
-| `estimatedHours` | `number` | - | - | Estimated hours |
-| `actualHours` | `number` | - | - | Actual hours |
-| `parentId` | `number` | - | - | Parent task ID, used for task grouping |
-| `children` | `Task[]` | - | - | Array of child tasks |
-| `collapsed` | `boolean` | - | `false` | Whether child tasks are collapsed |
-| `isParent` | `boolean` | - | - | Whether this is a parent task |
-| `type` | `string` | - | - | Task type, 'milestone' for milestone, 'milestone-group' for milestone group |
-| `description` | `string` | - | - | Task description |
-| `icon` | `string` | - | `'diamond'` | Task icon (for milestones), options: 'diamond', 'flag', 'star', 'rocket', etc. |
-| `level` | `number` | - | `0` | Task level (auto-calculated) |
-| `isTimerRunning` | `boolean` | - | `false` | Whether timer is running |
-| `timerStartTime` | `number` | - | - | Timer start time (timestamp) |
-| `timerEndTime` | `number` | - | - | Timer end time (timestamp) |
-| `timerStartDesc` | `string` | - | - | Description filled when timer starts |
-| `timerElapsedTime` | `number` | - | `0` | Elapsed time (milliseconds) |
-| `isEditable` | `boolean` | - | `true` | Whether individual task is editable (draggable, resizable), overrides global `allowDragAndResize` |
-| `[key: string]` | `unknown` | - | - | Supports custom property extensions, can add any additional fields |
+| Field | Type | Required | Default | Description |
+| ------------------ | ---------- | -------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `id` | `number` | ✅ | - | Unique task identifier |
+| `name` | `string` | ✅ | - | Task name |
+| `startDate` | `string` | - | - | Start date, format: 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm' |
+| `endDate` | `string` | - | - | End date, format: 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm' |
+| `progress` | `number` | - | `0` | Task progress, range 0-100 |
+| `predecessor` | `number[]` | - | - | Array of predecessor task IDs, standard format: `[1, 2, 3]`
**Compatible formats**: Also supports string `'1,2,3'` or string array `['1', '2', '3']`, component will auto-parse |
+| `assignee` | `string` | - | - | Task assignee |
+| `avatar` | `string` | - | - | Avatar URL of task assignee |
+| `estimatedHours` | `number` | - | - | Estimated hours |
+| `actualHours` | `number` | - | - | Actual hours |
+| `parentId` | `number` | - | - | Parent task ID, used for task grouping |
+| `children` | `Task[]` | - | - | Array of child tasks |
+| `collapsed` | `boolean` | - | `false` | Whether child tasks are collapsed |
+| `isParent` | `boolean` | - | - | Whether this is a parent task |
+| `type` | `string` | - | - | Task type, 'milestone' for milestone, 'milestone-group' for milestone group |
+| `description` | `string` | - | - | Task description |
+| `icon` | `string` | - | `'diamond'` | Task icon (for milestones), options: 'diamond', 'flag', 'star', 'rocket', etc. |
+| `level` | `number` | - | `0` | Task level (auto-calculated) |
+| `isTimerRunning` | `boolean` | - | `false` | Whether timer is running |
+| `timerStartTime` | `number` | - | - | Timer start time (timestamp) |
+| `timerEndTime` | `number` | - | - | Timer end time (timestamp) |
+| `timerStartDesc` | `string` | - | - | Description filled when timer starts |
+| `timerElapsedTime` | `number` | - | `0` | Elapsed time (milliseconds) |
+| `isEditable` | `boolean` | - | `true` | Whether individual task is editable (draggable, resizable), overrides global `allowDragAndResize` |
+| `[key: string]` | `unknown` | - | - | Supports custom property extensions, can add any additional fields |
> **Custom Property Extensions**: The Task interface supports adding arbitrary custom fields, such as: `priority`, `tags`, `status`, `department`, and other business-related fields.
->
+>
> **Predecessor Field Notes**:
+>
> - **Standard format** (recommended): `predecessor: [1, 2, 3]` - number array
-> **Compatible format 1**: `predecessor: '1,2,3'` - comma-separated string
+> **Compatible format 1**: `predecessor: '1,2,3'` - comma-separated string
> - **Compatible format 2**: `predecessor: ['1', '2', '3']` - string array
> - Component will automatically parse all formats into number array
> - No predecessors: use empty array `[]`, empty string `''`, or don't set this field
#### Task-Related Props
-| Prop | Type | Default | Description |
-|------|------|---------|-------------|
-| `tasks` | `Task[]` | `[]` | Array of task data |
-| `useDefaultDrawer` | `boolean` | `true` | Whether to use built-in task edit drawer (TaskDrawer) |
-| `taskBarConfig` | `TaskBarConfig` | `{}` | Task bar style configuration, see [TaskBarConfig Configuration](#taskbarconfig-configuration) |
-| `taskListConfig` | `TaskListConfig` | `undefined` | Task list configuration, see [TaskListConfig Configuration](#tasklistconfig-configuration) |
-| `autoSortByStartDate` | `boolean` | `false` | Whether to automatically sort tasks by start date |
+| Prop | Type | Default | Description |
+| --------------------- | ---------------- | ----------- | --------------------------------------------------------------------------------------------- |
+| `tasks` | `Task[]` | `[]` | Array of task data |
+| `useDefaultDrawer` | `boolean` | `true` | Whether to use built-in task edit drawer (TaskDrawer) |
+| `taskBarConfig` | `TaskBarConfig` | `{}` | Task bar style configuration, see [TaskBarConfig Configuration](#taskbarconfig-configuration) |
+| `taskListConfig` | `TaskListConfig` | `undefined` | Task list configuration, see [TaskListConfig Configuration](#tasklistconfig-configuration) |
+| `autoSortByStartDate` | `boolean` | `false` | Whether to automatically sort tasks by start date |
**Configuration Notes**:
+
- **Default mode**: `useDefaultDrawer=true` (default), double-click task to auto-open built-in TaskDrawer
- **Custom editor**: `useDefaultDrawer=false` disables built-in drawer, listen to `@task-double-click` event to open custom editor
- **Read-only mode**: `useDefaultDrawer=false` and don't listen to `@task-double-click` event, user double-click task has no response
@@ -433,22 +435,23 @@ Tasks are the core elements of the Gantt chart. The component provides complete
> **💡 Event-Driven Architecture**: Component adopts pure event-driven design. All user operations (add, edit, delete, drag, etc.) will trigger corresponding events for easy external listening and handling.
-| Event Name | Parameters | When Triggered | Description |
-|------------|------------|----------------|-------------|
-| `add-task` | - | When clicking toolbar "Add Task" button | Can be used for custom add task logic. If `useDefaultDrawer=true`, component will auto-open built-in TaskDrawer |
-| `task-click` | `(task: Task, event: MouseEvent) => void` | When clicking task bar | Triggered on single-click task |
-| `task-double-click` | `(task: Task) => void` | When double-clicking task bar | Double-click task **always triggers**. When `useDefaultDrawer=true`, component will additionally open built-in editor; when `false`, won't open. Event triggering is independent of property value |
-| `task-added` | `{ task: Task }` | After task added | Triggered after adding task via built-in TaskDrawer. **Note**: Component has auto-updated `tasks` data, external only needs to listen to this event for additional processing (like calling API to save) |
-| `task-updated` | `{ task: Task }` | After task updated | Triggered after updating task via built-in TaskDrawer or drag. **Note**: Component has auto-updated `tasks` data, external only needs to listen to this event for additional processing |
-| `task-deleted` | `{ task: Task }` | After task deleted | Triggered after deleting task via built-in TaskDrawer. **Note**: Component has auto-updated `tasks` data, external only needs to listen to this event for additional processing |
-| `taskbar-drag-end` | `(task: Task) => void` | When task bar drag ends | Task position changed, startDate and endDate updated. **Note**: Component has auto-updated `tasks` data |
-| `taskbar-resize-end` | `(task: Task) => void` | When task bar resize ends | Task duration changed, endDate updated. **Note**: Component has auto-updated `tasks` data |
-| `predecessor-added` | `{ targetTask: Task, newTask: Task }` | After adding predecessor via context menu | `targetTask` is the task to which predecessor is added, `newTask` is the newly created predecessor task |
-| `successor-added` | `{ targetTask: Task, newTask: Task }` | After adding successor via context menu | `targetTask` is the original task, `newTask` is the newly created successor task (its predecessor already contains targetTask.id) |
-| `timer-started` | `(task: Task) => void` | When task timer starts | Start recording task hours |
-| `timer-stopped` | `(task: Task) => void` | When task timer stops | Stop recording task hours |
+| Event Name | Parameters | When Triggered | Description |
+| -------------------- | ----------------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `add-task` | - | When clicking toolbar "Add Task" button | Can be used for custom add task logic. If `useDefaultDrawer=true`, component will auto-open built-in TaskDrawer |
+| `task-click` | `(task: Task, event: MouseEvent) => void` | When clicking task bar | Triggered on single-click task |
+| `task-double-click` | `(task: Task) => void` | When double-clicking task bar | Double-click task **always triggers**. When `useDefaultDrawer=true`, component will additionally open built-in editor; when `false`, won't open. Event triggering is independent of property value |
+| `task-added` | `{ task: Task }` | After task added | Triggered after adding task via built-in TaskDrawer. **Note**: Component has auto-updated `tasks` data, external only needs to listen to this event for additional processing (like calling API to save) |
+| `task-updated` | `{ task: Task }` | After task updated | Triggered after updating task via built-in TaskDrawer or drag. **Note**: Component has auto-updated `tasks` data, external only needs to listen to this event for additional processing |
+| `task-deleted` | `{ task: Task }` | After task deleted | Triggered after deleting task via built-in TaskDrawer. **Note**: Component has auto-updated `tasks` data, external only needs to listen to this event for additional processing |
+| `taskbar-drag-end` | `(task: Task) => void` | When task bar drag ends | Task position changed, startDate and endDate updated. **Note**: Component has auto-updated `tasks` data |
+| `taskbar-resize-end` | `(task: Task) => void` | When task bar resize ends | Task duration changed, endDate updated. **Note**: Component has auto-updated `tasks` data |
+| `predecessor-added` | `{ targetTask: Task, newTask: Task }` | After adding predecessor via context menu | `targetTask` is the task to which predecessor is added, `newTask` is the newly created predecessor task |
+| `successor-added` | `{ targetTask: Task, newTask: Task }` | After adding successor via context menu | `targetTask` is the original task, `newTask` is the newly created successor task (its predecessor already contains targetTask.id) |
+| `timer-started` | `(task: Task) => void` | When task timer starts | Start recording task hours |
+| `timer-stopped` | `(task: Task) => void` | When task timer stops | Stop recording task hours |
**Data Synchronization Notes**:
+
- ✅ **Component auto-updates internally**: For all task CRUD operations, component will auto-update `props.tasks` data
- ✅ **Events are for notification only**: External event listeners are mainly for: showing messages, calling backend APIs, updating other related data, etc.
- ❌ **Avoid duplicate operations**: Don't modify `tasks` data again in event handlers, otherwise it will cause duplicate updates
@@ -458,7 +461,7 @@ Tasks are the core elements of the Gantt chart. The component provides complete
```vue
**兼容格式**:也支持字符串 `'1,2,3'` 或字符串数组 `['1', '2', '3']`,组件会自动解析 |
-| `assignee` | `string` | - | - | 任务负责人 |
-| `avatar` | `string` | - | - | 任务负责人头像 URL |
-| `estimatedHours` | `number` | - | - | 预估工时(小时) |
-| `actualHours` | `number` | - | - | 实际工时(小时) |
-| `parentId` | `number` | - | - | 父任务 ID,用于任务分组 |
-| `children` | `Task[]` | - | - | 子任务数组 |
-| `collapsed` | `boolean` | - | `false` | 子任务是否折叠 |
-| `isParent` | `boolean` | - | - | 是否为父任务 |
-| `type` | `string` | - | - | 任务类型,'milestone' 表示里程碑,'milestone-group' 表示里程碑分组 |
-| `description` | `string` | - | - | 任务描述 |
-| `icon` | `string` | - | `'diamond'` | 任务图标(用于里程碑),可选值:'diamond', 'flag', 'star', 'rocket' 等 |
-| `level` | `number` | - | `0` | 任务层级(自动计算) |
-| `isTimerRunning` | `boolean` | - | `false` | 计时器是否运行中 |
-| `timerStartTime` | `number` | - | - | 计时开始时间(时间戳) |
-| `timerEndTime` | `number` | - | - | 计时结束时间(时间戳) |
-| `timerStartDesc` | `string` | - | - | 计时开始时填写的描述 |
-| `timerElapsedTime` | `number` | - | `0` | 已计时的时长(毫秒) |
-| `isEditable` | `boolean` | - | `true` | 单个任务是否可编辑(可拖拽、拉伸),优先级高于全局 `allowDragAndResize` |
-| `[key: string]` | `unknown` | - | - | 支持自定义属性扩展,可添加任意额外字段 |
+| 字段名 | 类型 | 必填 | 默认值 | 说明 |
+| ------------------ | ---------- | ---- | ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
+| `id` | `number` | ✅ | - | 任务唯一标识符 |
+| `name` | `string` | ✅ | - | 任务名称 |
+| `startDate` | `string` | - | - | 开始日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
+| `endDate` | `string` | - | - | 结束日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
+| `progress` | `number` | - | `0` | 任务进度,范围 0-100 |
+| `predecessor` | `number[]` | - | - | 前置任务 ID 数组,标准格式:`[1, 2, 3]`
**兼容格式**:也支持字符串 `'1,2,3'` 或字符串数组 `['1', '2', '3']`,组件会自动解析 |
+| `assignee` | `string` | - | - | 任务负责人 |
+| `avatar` | `string` | - | - | 任务负责人头像 URL |
+| `estimatedHours` | `number` | - | - | 预估工时(小时) |
+| `actualHours` | `number` | - | - | 实际工时(小时) |
+| `parentId` | `number` | - | - | 父任务 ID,用于任务分组 |
+| `children` | `Task[]` | - | - | 子任务数组 |
+| `collapsed` | `boolean` | - | `false` | 子任务是否折叠 |
+| `isParent` | `boolean` | - | - | 是否为父任务 |
+| `type` | `string` | - | - | 任务类型,'milestone' 表示里程碑,'milestone-group' 表示里程碑分组 |
+| `description` | `string` | - | - | 任务描述 |
+| `icon` | `string` | - | `'diamond'` | 任务图标(用于里程碑),可选值:'diamond', 'flag', 'star', 'rocket' 等 |
+| `level` | `number` | - | `0` | 任务层级(自动计算) |
+| `isTimerRunning` | `boolean` | - | `false` | 计时器是否运行中 |
+| `timerStartTime` | `number` | - | - | 计时开始时间(时间戳) |
+| `timerEndTime` | `number` | - | - | 计时结束时间(时间戳) |
+| `timerStartDesc` | `string` | - | - | 计时开始时填写的描述 |
+| `timerElapsedTime` | `number` | - | `0` | 已计时的时长(毫秒) |
+| `isEditable` | `boolean` | - | `true` | 单个任务是否可编辑(可拖拽、拉伸),优先级高于全局 `allowDragAndResize` |
+| `[key: string]` | `unknown` | - | - | 支持自定义属性扩展,可添加任意额外字段 |
> **自定义属性扩展**:Task 接口支持添加任意自定义字段,例如:`priority`、`tags`、`status`、`department` 等业务相关字段。
->
+>
> **前置任务字段说明**:
+>
> - **标准格式**(推荐):`predecessor: [1, 2, 3]` - number 数组
> - **兼容格式1**:`predecessor: '1,2,3'` - 逗号分隔的字符串
> - **兼容格式2**:`predecessor: ['1', '2', '3']` - 字符串数组
@@ -414,15 +415,16 @@ const handleMilestoneSaved = (milestone) => {
#### 任务相关属性
-| 属性名 | 类型 | 默认值 | 说明 |
-|--------|------|--------|------|
-| `tasks` | `Task[]` | `[]` | 任务数据数组 |
-| `useDefaultDrawer` | `boolean` | `true` | 是否使用内置的任务编辑抽屉(TaskDrawer) |
-| `taskBarConfig` | `TaskBarConfig` | `{}` | 任务条样式配置,详见 [TaskBarConfig 配置](#taskbarconfig-配置) |
-| `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置,详见 [TaskListConfig 配置](#tasklistconfig-配置) |
-| `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
+| 属性名 | 类型 | 默认值 | 说明 |
+| --------------------- | ---------------- | ----------- | -------------------------------------------------------------- |
+| `tasks` | `Task[]` | `[]` | 任务数据数组 |
+| `useDefaultDrawer` | `boolean` | `true` | 是否使用内置的任务编辑抽屉(TaskDrawer) |
+| `taskBarConfig` | `TaskBarConfig` | `{}` | 任务条样式配置,详见 [TaskBarConfig 配置](#taskbarconfig-配置) |
+| `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置,详见 [TaskListConfig 配置](#tasklistconfig-配置) |
+| `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
**配置说明**:
+
- **默认模式**:`useDefaultDrawer=true`(默认),双击任务自动打开内置 TaskDrawer
- **自定义编辑器**:`useDefaultDrawer=false` 禁用内置抽屉,监听 `@task-double-click` 事件打开自定义编辑器
- **只读模式**:`useDefaultDrawer=false` 且不监听 `@task-double-click` 事件,用户双击任务无反应
@@ -431,22 +433,23 @@ const handleMilestoneSaved = (milestone) => {
> **💡 事件驱动架构**:组件采用纯事件驱动设计,所有用户操作(添加、编辑、删除、拖拽等)都会触发对应事件,方便外部监听和处理。
-| 事件名 | 参数 | 触发时机 | 说明 |
-|--------|------|---------|------|
-| `add-task` | - | 点击工具栏"添加任务"按钮时 | 可用于自定义新增任务逻辑。如 `useDefaultDrawer=true`,组件会自动打开内置 TaskDrawer |
-| `task-click` | `(task: Task, event: MouseEvent) => void` | 点击任务条时 | 单击任务触发 |
-| `task-double-click` | `(task: Task) => void` | 双击任务条时 | 双击任务时**始终触发**。`useDefaultDrawer=true` 时组件会额外打开内置编辑器,`false` 时不打开。事件触发与属性值无关 |
-| `task-added` | `{ task: Task }` | 任务添加后 | 通过内置 TaskDrawer 添加任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理(如调用 API 保存) |
-| `task-updated` | `{ task: Task }` | 任务更新后 | 通过内置 TaskDrawer 或拖拽更新任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理 |
-| `task-deleted` | `{ task: Task }` | 任务删除后 | 通过内置 TaskDrawer 删除任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理 |
-| `taskbar-drag-end` | `(task: Task) => void` | 拖拽任务条结束时 | 任务位置变化,startDate 和 endDate 已更新。**注意**:组件已自动更新 `tasks` 数据 |
-| `taskbar-resize-end` | `(task: Task) => void` | 调整任务条大小结束时 | 任务时长变化,endDate 已更新。**注意**:组件已自动更新 `tasks` 数据 |
-| `predecessor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加前置任务后 | `targetTask` 是被添加前置任务的任务,`newTask` 是新创建的前置任务 |
-| `successor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加后置任务后 | `targetTask` 是原任务,`newTask` 是新创建的后置任务(其 predecessor 已包含 targetTask.id) |
-| `timer-started` | `(task: Task) => void` | 任务计时器启动时 | 开始记录任务工时 |
-| `timer-stopped` | `(task: Task) => void` | 任务计时器停止时 | 停止记录任务工时 |
+| 事件名 | 参数 | 触发时机 | 说明 |
+| -------------------- | ----------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
+| `add-task` | - | 点击工具栏"添加任务"按钮时 | 可用于自定义新增任务逻辑。如 `useDefaultDrawer=true`,组件会自动打开内置 TaskDrawer |
+| `task-click` | `(task: Task, event: MouseEvent) => void` | 点击任务条时 | 单击任务触发 |
+| `task-double-click` | `(task: Task) => void` | 双击任务条时 | 双击任务时**始终触发**。`useDefaultDrawer=true` 时组件会额外打开内置编辑器,`false` 时不打开。事件触发与属性值无关 |
+| `task-added` | `{ task: Task }` | 任务添加后 | 通过内置 TaskDrawer 添加任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理(如调用 API 保存) |
+| `task-updated` | `{ task: Task }` | 任务更新后 | 通过内置 TaskDrawer 或拖拽更新任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理 |
+| `task-deleted` | `{ task: Task }` | 任务删除后 | 通过内置 TaskDrawer 删除任务后触发。**注意**:组件已自动更新 `tasks` 数据,外部只需监听此事件做额外处理 |
+| `taskbar-drag-end` | `(task: Task) => void` | 拖拽任务条结束时 | 任务位置变化,startDate 和 endDate 已更新。**注意**:组件已自动更新 `tasks` 数据 |
+| `taskbar-resize-end` | `(task: Task) => void` | 调整任务条大小结束时 | 任务时长变化,endDate 已更新。**注意**:组件已自动更新 `tasks` 数据 |
+| `predecessor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加前置任务后 | `targetTask` 是被添加前置任务的任务,`newTask` 是新创建的前置任务 |
+| `successor-added` | `{ targetTask: Task, newTask: Task }` | 通过右键菜单添加后置任务后 | `targetTask` 是原任务,`newTask` 是新创建的后置任务(其 predecessor 已包含 targetTask.id) |
+| `timer-started` | `(task: Task) => void` | 任务计时器启动时 | 开始记录任务工时 |
+| `timer-stopped` | `(task: Task) => void` | 任务计时器停止时 | 停止记录任务工时 |
**数据同步说明**:
+
- ✅ **组件内部自动更新**:所有任务的增删改操作,组件都会自动更新 `props.tasks` 数据
- ✅ **事件仅做通知**:外部监听事件主要用于:显示提示消息、调用后端 API、更新其他相关数据等
- ❌ **避免重复操作**:不要在事件处理器中再次修改 `tasks` 数据,否则会导致重复更新
@@ -456,7 +459,7 @@ const handleMilestoneSaved = (milestone) => {
```vue