From 308a8d142157858d157d685d4a67643b748ad932 Mon Sep 17 00:00:00 2001 From: "LINING-PC\\lining" Date: Mon, 3 Nov 2025 14:49:10 +0800 Subject: [PATCH] =?UTF-8?q?v=201.4.2=20-=20=E5=BE=BD=E7=AB=A0=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-EN.md | 755 +++++++++++++++++++++++++------------------------- README.md | 759 +++++++++++++++++++++++++-------------------------- 2 files changed, 751 insertions(+), 763 deletions(-) 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 @@

- npm version + npm version + + + npm total MIT License @@ -105,10 +108,7 @@ Create your first Gantt chart: ```vue @@ -123,7 +123,7 @@ const tasks = ref([ name: 'Project Kickoff', startDate: '2025-01-01', endDate: '2025-01-10', - progress: 100 + progress: 100, }, { id: 2, @@ -131,7 +131,7 @@ const tasks = ref([ startDate: '2025-01-11', endDate: '2025-01-20', progress: 80, - predecessor: [1] + predecessor: [1], }, { id: 3, @@ -139,8 +139,8 @@ const tasks = ref([ startDate: '2025-01-21', endDate: '2025-02-05', progress: 50, - predecessor: [2] - } + predecessor: [2], + }, ]) const milestones = ref([ @@ -148,8 +148,8 @@ const milestones = ref([ id: 101, name: 'Project Approval', date: '2025-01-01', - type: 'milestone' - } + type: 'milestone', + }, ]) ``` @@ -158,6 +158,7 @@ const milestones = ref([ Recommended: DOVE VPN for fast and stable access. (Note: Please use VPN services legally) ## 🌞 NPM Package Usage Example + Please refer to the npm-demo folder in the project. It is a standalone project that can be opened and run independently using your IDE. Before running, make sure to install the Element Plus library and the jordium-gantt-vue3 plugin package. @@ -168,6 +169,7 @@ npm install element-plus npm install jordium-gantt-vue3 npm run dev ``` + --- ## 📖 Component Guide @@ -178,68 +180,69 @@ npm run dev #### Basic Props -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `tasks` | `Task[]` | `[]` | Array of task data | -| `milestones` | `Task[]` | `[]` | Array of milestone data (Note: Type is Task[], must set type='milestone') | -| `showToolbar` | `boolean` | `true` | Whether to show the toolbar | -| `useDefaultDrawer` | `boolean` | `true` | Whether to use the built-in task edit drawer (TaskDrawer) | -| `useDefaultMilestoneDialog` | `boolean` | `true` | Whether to use the built-in milestone edit dialog (MilestoneDialog) | -| `autoSortByStartDate` | `boolean` | `false` | Whether to automatically sort tasks by start date | -| `allowDragAndResize` | `boolean` | `true` | Whether to allow dragging and resizing tasks/milestones | +| Prop | Type | Default | Description | +| --------------------------- | --------- | ------- | ------------------------------------------------------------------------- | +| `tasks` | `Task[]` | `[]` | Array of task data | +| `milestones` | `Task[]` | `[]` | Array of milestone data (Note: Type is Task[], must set type='milestone') | +| `showToolbar` | `boolean` | `true` | Whether to show the toolbar | +| `useDefaultDrawer` | `boolean` | `true` | Whether to use the built-in task edit drawer (TaskDrawer) | +| `useDefaultMilestoneDialog` | `boolean` | `true` | Whether to use the built-in milestone edit dialog (MilestoneDialog) | +| `autoSortByStartDate` | `boolean` | `false` | Whether to automatically sort tasks by start date | +| `allowDragAndResize` | `boolean` | `true` | Whether to allow dragging and resizing tasks/milestones | #### Configuration Object Props For complete configuration object documentation, see [⚙️ Configuration & Customization](#⚙️-configuration--customization) section. -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `toolbarConfig` | `ToolbarConfig` | `{}` | Toolbar configuration | -| `taskListConfig` | `TaskListConfig` | `undefined` | Task list configuration | -| `taskBarConfig` | `TaskBarConfig` | `undefined` | Task bar style configuration | -| `localeMessages` | `Partial` | `undefined` | Custom localization messages | -| `workingHours` | `WorkingHours` | `{ morning: { start: 8, end: 11 }, afternoon: { start: 13, end: 17 } }` | Working hours configuration | +| Prop | Type | Default | Description | +| ---------------- | ---------------------------- | ----------------------------------------------------------------------- | ---------------------------- | +| `toolbarConfig` | `ToolbarConfig` | `{}` | Toolbar configuration | +| `taskListConfig` | `TaskListConfig` | `undefined` | Task list configuration | +| `taskBarConfig` | `TaskBarConfig` | `undefined` | Task bar style configuration | +| `localeMessages` | `Partial` | `undefined` | Custom localization messages | +| `workingHours` | `WorkingHours` | `{ morning: { start: 8, end: 11 }, afternoon: { start: 13, end: 17 } }` | Working hours configuration | #### Callback Props -| Prop | Type | Description | -|------|------|-------------| -| `onTodayLocate` | `() => void` | Toolbar "Today" button click callback | -| `onExportCsv` | `() => boolean \| void` | Toolbar "Export CSV" button click callback, return `false` to prevent default export | -| `onExportPdf` | `() => void` | Toolbar "Export PDF" button click callback | -| `onLanguageChange` | `(lang: 'zh-CN' \| 'en-US') => void` | Language switch callback | -| `onThemeChange` | `(isDark: boolean) => void` | Theme switch callback | -| `onFullscreenChange` | `(isFullscreen: boolean) => void` | Fullscreen toggle callback | -| `onExpandAll` | `() => void` | Toolbar "Expand All" button click callback | -| `onCollapseAll` | `() => void` | Toolbar "Collapse All" button click callback | +| Prop | Type | Description | +| -------------------- | ------------------------------------ | ------------------------------------------------------------------------------------ | +| `onTodayLocate` | `() => void` | Toolbar "Today" button click callback | +| `onExportCsv` | `() => boolean \| void` | Toolbar "Export CSV" button click callback, return `false` to prevent default export | +| `onExportPdf` | `() => void` | Toolbar "Export PDF" button click callback | +| `onLanguageChange` | `(lang: 'zh-CN' \| 'en-US') => void` | Language switch callback | +| `onThemeChange` | `(isDark: boolean) => void` | Theme switch callback | +| `onFullscreenChange` | `(isFullscreen: boolean) => void` | Fullscreen toggle callback | +| `onExpandAll` | `() => void` | Toolbar "Expand All" button click callback | +| `onCollapseAll` | `() => void` | Toolbar "Collapse All" button click callback | #### Component Events For complete event documentation, see: + - **Task-related events**: See [Task Management](#task-management) section below - **Milestone-related events**: See [Milestone Management](#milestone-management) section below **Event List Overview:** -| Event Name | Parameters | Description | -|------------|------------|-------------| -| `add-task` | - | Clicked toolbar "Add Task" button | -| `task-click` | `(task: Task, event: MouseEvent)` | Clicked task | -| `task-double-click` | `(task: Task)` | Double-clicked task | -| `task-added` | `{ task: Task }` | Triggered after task added | -| `task-updated` | `{ task: Task }` | Triggered after task updated | -| `task-deleted` | `{ task: Task }` | Triggered after task deleted | -| `taskbar-drag-end` | `(task: Task)` | Task drag ended | -| `taskbar-resize-end` | `(task: Task)` | Task resize ended | -| `predecessor-added` | `{ targetTask, newTask }` | Added predecessor task | -| `successor-added` | `{ targetTask, newTask }` | Added successor task | -| `timer-started` | `(task: Task)` | Task timer started | -| `timer-stopped` | `(task: Task)` | Task timer stopped | -| `add-milestone` | - | Clicked toolbar "Add Milestone" button | -| `milestone-saved` | `(milestone: Task)` | Milestone saved | -| `milestone-deleted` | `{ milestoneId: number }` | Milestone deleted | -| `milestone-icon-changed` | `{ milestoneId, icon }` | Milestone icon changed | -| `milestone-drag-end` | `(milestone: Task)` | Milestone drag ended | +| Event Name | Parameters | Description | +| ------------------------ | --------------------------------- | -------------------------------------- | +| `add-task` | - | Clicked toolbar "Add Task" button | +| `task-click` | `(task: Task, event: MouseEvent)` | Clicked task | +| `task-double-click` | `(task: Task)` | Double-clicked task | +| `task-added` | `{ task: Task }` | Triggered after task added | +| `task-updated` | `{ task: Task }` | Triggered after task updated | +| `task-deleted` | `{ task: Task }` | Triggered after task deleted | +| `taskbar-drag-end` | `(task: Task)` | Task drag ended | +| `taskbar-resize-end` | `(task: Task)` | Task resize ended | +| `predecessor-added` | `{ targetTask, newTask }` | Added predecessor task | +| `successor-added` | `{ targetTask, newTask }` | Added successor task | +| `timer-started` | `(task: Task)` | Task timer started | +| `timer-stopped` | `(task: Task)` | Task timer stopped | +| `add-milestone` | - | Clicked toolbar "Add Milestone" button | +| `milestone-saved` | `(milestone: Task)` | Milestone saved | +| `milestone-deleted` | `{ milestoneId: number }` | Milestone deleted | +| `milestone-icon-changed` | `{ milestoneId, icon }` | Milestone icon changed | +| `milestone-drag-end` | `(milestone: Task)` | Milestone drag ended | #### Example 1: Simplest Gantt Chart @@ -261,8 +264,8 @@ const tasks = ref([ name: 'Task 1', startDate: '2025-01-01', endDate: '2025-01-10', - progress: 100 - } + progress: 100, + }, ]) ``` @@ -272,10 +275,7 @@ const tasks = ref([ ```vue @@ -290,8 +290,8 @@ const tasks = ref([ name: 'Project Kickoff', startDate: '2025-01-01', endDate: '2025-01-10', - progress: 100 - } + progress: 100, + }, ]) const milestones = ref([ @@ -300,8 +300,8 @@ const milestones = ref([ name: 'Project Approval', startDate: '2025-01-01', type: 'milestone', - icon: 'diamond' - } + icon: 'diamond', + }, ]) ``` @@ -316,10 +316,10 @@ const milestones = ref([ - +

- { name: 'New Task', startDate: new Date().toISOString().split('T')[0], endDate: new Date().toISOString().split('T')[0], - progress: 0 + progress: 0, } tasks.value.push(newTask) } @@ -354,16 +354,16 @@ const addMilestone = () => { id: Date.now(), name: 'New Milestone', startDate: new Date().toISOString().split('T')[0], - type: 'milestone' + type: 'milestone', } milestones.value.push(newMilestone) } -const handleTaskAdded = (e) => { +const handleTaskAdded = e => { console.log('Task added:', e.task) } -const handleMilestoneSaved = (milestone) => { +const handleMilestoneSaved = milestone => { console.log('Milestone saved:', milestone) } @@ -377,54 +377,56 @@ Tasks are the core elements of the Gantt chart. The component provides complete #### Task Data Structure -| 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 | +| 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