v 1.4.2 - 徽章更新

This commit is contained in:
LINING-PC\lining
2025-11-03 14:49:10 +08:00
parent cf888f411d
commit 308a8d1421
2 changed files with 751 additions and 763 deletions
+120 -123
View File
@@ -2,7 +2,10 @@
<p align="center"> <p align="center">
<a href="https://www.npmjs.com/package/jordium-gantt-vue3"> <a href="https://www.npmjs.com/package/jordium-gantt-vue3">
<img src="https://img.shields.io/npm/v/jordium-gantt-vue3.svg" alt="npm version"> <img src="https://img.shields.io/npm/v/jordium-gantt-vue3?style=flat-square" alt="npm version">
</a>
<a href="https://www.npmjs.com/package/jordium-gantt-vue3">
<img src="https://img.shields.io/npm/dt/jordium-gantt-vue3?style=flat-square" alt="npm total">
</a> </a>
<a href="https://opensource.org/licenses/MIT"> <a href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"> <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License">
@@ -105,10 +108,7 @@ Create your first Gantt chart:
```vue ```vue
<template> <template>
<div style="height: 600px;"> <div style="height: 600px;">
<GanttChart <GanttChart :tasks="tasks" :milestones="milestones" />
:tasks="tasks"
:milestones="milestones"
/>
</div> </div>
</template> </template>
@@ -123,7 +123,7 @@ const tasks = ref([
name: 'Project Kickoff', name: 'Project Kickoff',
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 100 progress: 100,
}, },
{ {
id: 2, id: 2,
@@ -131,7 +131,7 @@ const tasks = ref([
startDate: '2025-01-11', startDate: '2025-01-11',
endDate: '2025-01-20', endDate: '2025-01-20',
progress: 80, progress: 80,
predecessor: [1] predecessor: [1],
}, },
{ {
id: 3, id: 3,
@@ -139,8 +139,8 @@ const tasks = ref([
startDate: '2025-01-21', startDate: '2025-01-21',
endDate: '2025-02-05', endDate: '2025-02-05',
progress: 50, progress: 50,
predecessor: [2] predecessor: [2],
} },
]) ])
const milestones = ref([ const milestones = ref([
@@ -148,8 +148,8 @@ const milestones = ref([
id: 101, id: 101,
name: 'Project Approval', name: 'Project Approval',
date: '2025-01-01', date: '2025-01-01',
type: 'milestone' type: 'milestone',
} },
]) ])
</script> </script>
``` ```
@@ -158,6 +158,7 @@ const milestones = ref([
<span><strong>Recommended: <a href="https://dovee.cc/a.php?anaxjgyz1ozZq2B">DOVE</a> VPN for fast and stable access.</strong></span> <span style="color:red;">(Note: Please use VPN services legally)</span> <span><strong>Recommended: <a href="https://dovee.cc/a.php?anaxjgyz1ozZq2B">DOVE</a> VPN for fast and stable access.</strong></span> <span style="color:red;">(Note: Please use VPN services legally)</span>
## 🌞 NPM Package Usage Example ## 🌞 NPM Package Usage Example
Please refer to the npm-demo folder in the project. 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. 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. 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 install jordium-gantt-vue3
npm run dev npm run dev
``` ```
--- ---
## 📖 Component Guide ## 📖 Component Guide
@@ -179,7 +181,7 @@ npm run dev
#### Basic Props #### Basic Props
| Prop | Type | Default | Description | | Prop | Type | Default | Description |
|------|------|---------|-------------| | --------------------------- | --------- | ------- | ------------------------------------------------------------------------- |
| `tasks` | `Task[]` | `[]` | Array of task data | | `tasks` | `Task[]` | `[]` | Array of task data |
| `milestones` | `Task[]` | `[]` | Array of milestone data (Note: Type is Task[], must set type='milestone') | | `milestones` | `Task[]` | `[]` | Array of milestone data (Note: Type is Task[], must set type='milestone') |
| `showToolbar` | `boolean` | `true` | Whether to show the toolbar | | `showToolbar` | `boolean` | `true` | Whether to show the toolbar |
@@ -193,7 +195,7 @@ npm run dev
For complete configuration object documentation, see [⚙️ Configuration & Customization](#⚙️-configuration--customization) section. For complete configuration object documentation, see [⚙️ Configuration & Customization](#⚙️-configuration--customization) section.
| Prop | Type | Default | Description | | Prop | Type | Default | Description |
|------|------|---------|-------------| | ---------------- | ---------------------------- | ----------------------------------------------------------------------- | ---------------------------- |
| `toolbarConfig` | `ToolbarConfig` | `{}` | Toolbar configuration | | `toolbarConfig` | `ToolbarConfig` | `{}` | Toolbar configuration |
| `taskListConfig` | `TaskListConfig` | `undefined` | Task list configuration | | `taskListConfig` | `TaskListConfig` | `undefined` | Task list configuration |
| `taskBarConfig` | `TaskBarConfig` | `undefined` | Task bar style configuration | | `taskBarConfig` | `TaskBarConfig` | `undefined` | Task bar style configuration |
@@ -203,7 +205,7 @@ For complete configuration object documentation, see [⚙️ Configuration & Cus
#### Callback Props #### Callback Props
| Prop | Type | Description | | Prop | Type | Description |
|------|------|-------------| | -------------------- | ------------------------------------ | ------------------------------------------------------------------------------------ |
| `onTodayLocate` | `() => void` | Toolbar "Today" button click callback | | `onTodayLocate` | `() => void` | Toolbar "Today" button click callback |
| `onExportCsv` | `() => boolean \| void` | Toolbar "Export CSV" button click callback, return `false` to prevent default export | | `onExportCsv` | `() => boolean \| void` | Toolbar "Export CSV" button click callback, return `false` to prevent default export |
| `onExportPdf` | `() => void` | Toolbar "Export PDF" button click callback | | `onExportPdf` | `() => void` | Toolbar "Export PDF" button click callback |
@@ -216,13 +218,14 @@ For complete configuration object documentation, see [⚙️ Configuration & Cus
#### Component Events #### Component Events
For complete event documentation, see: For complete event documentation, see:
- **Task-related events**: See [Task Management](#task-management) section below - **Task-related events**: See [Task Management](#task-management) section below
- **Milestone-related events**: See [Milestone Management](#milestone-management) section below - **Milestone-related events**: See [Milestone Management](#milestone-management) section below
**Event List Overview:** **Event List Overview:**
| Event Name | Parameters | Description | | Event Name | Parameters | Description |
|------------|------------|-------------| | ------------------------ | --------------------------------- | -------------------------------------- |
| `add-task` | - | Clicked toolbar "Add Task" button | | `add-task` | - | Clicked toolbar "Add Task" button |
| `task-click` | `(task: Task, event: MouseEvent)` | Clicked task | | `task-click` | `(task: Task, event: MouseEvent)` | Clicked task |
| `task-double-click` | `(task: Task)` | Double-clicked task | | `task-double-click` | `(task: Task)` | Double-clicked task |
@@ -261,8 +264,8 @@ const tasks = ref([
name: 'Task 1', name: 'Task 1',
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 100 progress: 100,
} },
]) ])
</script> </script>
``` ```
@@ -272,10 +275,7 @@ const tasks = ref([
```vue ```vue
<template> <template>
<div style="height: 600px;"> <div style="height: 600px;">
<GanttChart <GanttChart :tasks="tasks" :milestones="milestones" />
:tasks="tasks"
:milestones="milestones"
/>
</div> </div>
</template> </template>
@@ -290,8 +290,8 @@ const tasks = ref([
name: 'Project Kickoff', name: 'Project Kickoff',
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 100 progress: 100,
} },
]) ])
const milestones = ref([ const milestones = ref([
@@ -300,8 +300,8 @@ const milestones = ref([
name: 'Project Approval', name: 'Project Approval',
startDate: '2025-01-01', startDate: '2025-01-01',
type: 'milestone', type: 'milestone',
icon: 'diamond' icon: 'diamond',
} },
]) ])
</script> </script>
``` ```
@@ -344,7 +344,7 @@ const addTask = () => {
name: 'New Task', name: 'New Task',
startDate: new Date().toISOString().split('T')[0], startDate: new Date().toISOString().split('T')[0],
endDate: new Date().toISOString().split('T')[0], endDate: new Date().toISOString().split('T')[0],
progress: 0 progress: 0,
} }
tasks.value.push(newTask) tasks.value.push(newTask)
} }
@@ -354,16 +354,16 @@ const addMilestone = () => {
id: Date.now(), id: Date.now(),
name: 'New Milestone', name: 'New Milestone',
startDate: new Date().toISOString().split('T')[0], startDate: new Date().toISOString().split('T')[0],
type: 'milestone' type: 'milestone',
} }
milestones.value.push(newMilestone) milestones.value.push(newMilestone)
} }
const handleTaskAdded = (e) => { const handleTaskAdded = e => {
console.log('Task added:', e.task) console.log('Task added:', e.task)
} }
const handleMilestoneSaved = (milestone) => { const handleMilestoneSaved = milestone => {
console.log('Milestone saved:', milestone) console.log('Milestone saved:', milestone)
} }
</script> </script>
@@ -378,7 +378,7 @@ Tasks are the core elements of the Gantt chart. The component provides complete
#### Task Data Structure #### Task Data Structure
| Field | Type | Required | Default | Description | | Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------| | ------------------ | ---------- | -------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | `number` | ✅ | - | Unique task identifier | | `id` | `number` | ✅ | - | Unique task identifier |
| `name` | `string` | ✅ | - | Task name | | `name` | `string` | ✅ | - | Task name |
| `startDate` | `string` | - | - | Start date, format: 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm' | | `startDate` | `string` | - | - | Start date, format: 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm' |
@@ -408,6 +408,7 @@ Tasks are the core elements of the Gantt chart. The component provides complete
> **Custom Property Extensions**: The Task interface supports adding arbitrary custom fields, such as: `priority`, `tags`, `status`, `department`, and other business-related 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**: > **Predecessor Field Notes**:
>
> - **Standard format** (recommended): `predecessor: [1, 2, 3]` - number array > - **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 > - **Compatible format 2**: `predecessor: ['1', '2', '3']` - string array
@@ -417,7 +418,7 @@ Tasks are the core elements of the Gantt chart. The component provides complete
#### Task-Related Props #### Task-Related Props
| Prop | Type | Default | Description | | Prop | Type | Default | Description |
|------|------|---------|-------------| | --------------------- | ---------------- | ----------- | --------------------------------------------------------------------------------------------- |
| `tasks` | `Task[]` | `[]` | Array of task data | | `tasks` | `Task[]` | `[]` | Array of task data |
| `useDefaultDrawer` | `boolean` | `true` | Whether to use built-in task edit drawer (TaskDrawer) | | `useDefaultDrawer` | `boolean` | `true` | Whether to use built-in task edit drawer (TaskDrawer) |
| `taskBarConfig` | `TaskBarConfig` | `{}` | Task bar style configuration, see [TaskBarConfig Configuration](#taskbarconfig-configuration) | | `taskBarConfig` | `TaskBarConfig` | `{}` | Task bar style configuration, see [TaskBarConfig Configuration](#taskbarconfig-configuration) |
@@ -425,6 +426,7 @@ Tasks are the core elements of the Gantt chart. The component provides complete
| `autoSortByStartDate` | `boolean` | `false` | Whether to automatically sort tasks by start date | | `autoSortByStartDate` | `boolean` | `false` | Whether to automatically sort tasks by start date |
**Configuration Notes**: **Configuration Notes**:
- **Default mode**: `useDefaultDrawer=true` (default), double-click task to auto-open built-in TaskDrawer - **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 - **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 - **Read-only mode**: `useDefaultDrawer=false` and don't listen to `@task-double-click` event, user double-click task has no response
@@ -434,7 +436,7 @@ 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-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 | | 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 | | `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-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-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 |
@@ -449,6 +451,7 @@ Tasks are the core elements of the Gantt chart. The component provides complete
| `timer-stopped` | `(task: Task) => void` | When task timer stops | Stop recording task hours | | `timer-stopped` | `(task: Task) => void` | When task timer stops | Stop recording task hours |
**Data Synchronization Notes**: **Data Synchronization Notes**:
-**Component auto-updates internally**: For all task CRUD operations, component will auto-update `props.tasks` data -**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. -**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 -**Avoid duplicate operations**: Don't modify `tasks` data again in event handlers, otherwise it will cause duplicate updates
@@ -494,7 +497,7 @@ const tasks = ref<Task[]>([
progress: 60, progress: 60,
assignee: 'Bob', assignee: 'Bob',
predecessor: [1], // Depends on task 1 predecessor: [1], // Depends on task 1
} },
]) ])
// Toolbar "Add Task" button click event // Toolbar "Add Task" button click event
@@ -567,7 +570,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 100, progress: 100,
predecessor: [] // No predecessors predecessor: [], // No predecessors
}, },
{ {
id: 2, id: 2,
@@ -575,7 +578,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-11', startDate: '2025-01-11',
endDate: '2025-01-20', endDate: '2025-01-20',
progress: 80, progress: 80,
predecessor: [1] // Depends on task 1 (Requirements Analysis) predecessor: [1], // Depends on task 1 (Requirements Analysis)
}, },
{ {
id: 3, id: 3,
@@ -583,7 +586,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-11', startDate: '2025-01-11',
endDate: '2025-01-18', endDate: '2025-01-18',
progress: 90, progress: 90,
predecessor: [1] // Depends on task 1 predecessor: [1], // Depends on task 1
}, },
{ {
id: 4, id: 4,
@@ -591,7 +594,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-21', startDate: '2025-01-21',
endDate: '2025-02-10', endDate: '2025-02-10',
progress: 60, progress: 60,
predecessor: [2] // Depends on task 2 (System Design) predecessor: [2], // Depends on task 2 (System Design)
}, },
{ {
id: 5, id: 5,
@@ -599,7 +602,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-19', startDate: '2025-01-19',
endDate: '2025-02-08', endDate: '2025-02-08',
progress: 70, progress: 70,
predecessor: [2, 3] // Depends on both task 2 and 3 predecessor: [2, 3], // Depends on both task 2 and 3
}, },
{ {
id: 6, id: 6,
@@ -607,8 +610,8 @@ const tasks = ref<Task[]>([
startDate: '2025-02-11', startDate: '2025-02-11',
endDate: '2025-02-20', endDate: '2025-02-20',
progress: 30, progress: 30,
predecessor: [4, 5] // Depends on frontend and backend development completion predecessor: [4, 5], // Depends on frontend and backend development completion
} },
]) ])
// Triggered when adding predecessor via context menu // Triggered when adding predecessor via context menu
@@ -630,6 +633,7 @@ const handleSuccessorAdded = (event: { targetTask: Task; newTask: Task }) => {
``` ```
**Dependency Relationship Notes**: **Dependency Relationship Notes**:
- **`predecessor` field supports multiple formats**: - **`predecessor` field supports multiple formats**:
- Standard format (recommended): `[1, 2, 3]` - number array - Standard format (recommended): `[1, 2, 3]` - number array
- Compatible format 1: `'1,2,3'` - comma-separated string - Compatible format 1: `'1,2,3'` - comma-separated string
@@ -698,7 +702,7 @@ const handleAddMilestone = () => {
console.log('Preparing to add milestone (triggered by custom button)') console.log('Preparing to add milestone (triggered by custom button)')
} }
const handleTaskAdded = (e) => { const handleTaskAdded = e => {
console.log('Task added:', e.task) console.log('Task added:', e.task)
// Call API to save... // Call API to save...
} }
@@ -706,6 +710,7 @@ const handleTaskAdded = (e) => {
``` ```
> **💡 Flexibility Design**: > **💡 Flexibility Design**:
>
> - Show toolbar + default editor: Simplest out-of-the-box approach > - Show toolbar + default editor: Simplest out-of-the-box approach
> - Hide toolbar + custom buttons + default editor: Custom control bar style while keeping default edit functionality > - Hide toolbar + custom buttons + default editor: Custom control bar style while keeping default edit functionality
> - Hide toolbar + custom buttons + custom editor: Fully customize all interaction logic > - Hide toolbar + custom buttons + custom editor: Fully customize all interaction logic
@@ -721,7 +726,7 @@ Milestones are used to mark important time points in a project, such as project
#### Milestone Data Structure #### Milestone Data Structure
| Field | Type | Required | Default | Description | | Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------| | ------------- | -------- | -------- | ------------- | --------------------------------------------------------------------------- |
| `id` | `number` | ✅ | - | Unique milestone identifier | | `id` | `number` | ✅ | - | Unique milestone identifier |
| `name` | `string` | ✅ | - | Milestone name | | `name` | `string` | ✅ | - | Milestone name |
| `startDate` | `string` | ✅ | - | Milestone date, format: 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm' | | `startDate` | `string` | ✅ | - | Milestone date, format: 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm' |
@@ -736,16 +741,18 @@ Milestones are used to mark important time points in a project, such as project
#### Milestone-Related Props #### Milestone-Related Props
| Prop | Type | Default | Description | | Prop | Type | Default | Description |
|------|------|---------|-------------| | --------------------------- | --------- | ------- | ----------------------------------------------------------------- |
| `milestones` | `Task[]` | `[]` | Array of milestone data (type is Task[], ensure type='milestone') | | `milestones` | `Task[]` | `[]` | Array of milestone data (type is Task[], ensure type='milestone') |
| `useDefaultMilestoneDialog` | `boolean` | `true` | Whether to use built-in milestone edit dialog (MilestoneDialog) | | `useDefaultMilestoneDialog` | `boolean` | `true` | Whether to use built-in milestone edit dialog (MilestoneDialog) |
**Configuration Notes**: **Configuration Notes**:
- **Default mode**: `useDefaultMilestoneDialog=true` (default), double-click milestone to auto-open built-in MilestoneDialog - **Default mode**: `useDefaultMilestoneDialog=true` (default), double-click milestone to auto-open built-in MilestoneDialog
- **Disable editor**: `useDefaultMilestoneDialog=false`, double-click milestone has no response (component doesn't open any editor) - **Disable editor**: `useDefaultMilestoneDialog=false`, double-click milestone has no response (component doesn't open any editor)
- **Custom editor**: Can listen to `onMilestoneDoubleClick` callback or related events to implement custom editing logic - **Custom editor**: Can listen to `onMilestoneDoubleClick` callback or related events to implement custom editing logic
> **💡 Differences Between Milestones and Tasks**: > **💡 Differences Between Milestones and Tasks**:
>
> - Milestone data is managed independently via `milestones` prop, separate from `tasks` > - Milestone data is managed independently via `milestones` prop, separate from `tasks`
> - Milestone object's `type` field must be set to `'milestone'` > - Milestone object's `type` field must be set to `'milestone'`
> - Milestones don't support child tasks, dependency relationships, and other complex structures > - Milestones don't support child tasks, dependency relationships, and other complex structures
@@ -755,13 +762,12 @@ Milestones are used to mark important time points in a project, such as project
> **⚠️ Deprecated**: Please use the new event-driven API (see "Milestone Events" section below) > **⚠️ Deprecated**: Please use the new event-driven API (see "Milestone Events" section below)
#### Milestone Events #### Milestone Events
> **💡 Event-Driven Architecture**: Milestone management adopts event-driven design. Using event API is recommended over callback functions. > **💡 Event-Driven Architecture**: Milestone management adopts event-driven design. Using event API is recommended over callback functions.
| Event Name | Parameters | When Triggered | Description | | Event Name | Parameters | When Triggered | Description |
|------------|------------|----------------|-------------| | ------------------------ | --------------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `add-milestone` | - | When clicking toolbar "Add Milestone" button | Can be used for custom add milestone logic. If `useDefaultMilestoneDialog=true`, component will auto-open built-in MilestoneDialog | | `add-milestone` | - | When clicking toolbar "Add Milestone" button | Can be used for custom add milestone logic. If `useDefaultMilestoneDialog=true`, component will auto-open built-in MilestoneDialog |
| `milestone-saved` | `(milestone: Task) => void` | After milestone saved (add or edit) | Triggered after saving milestone via built-in MilestoneDialog. **Note**: Component has auto-updated `milestones` data, external only needs to listen to this event for additional processing (like calling API to save) | | `milestone-saved` | `(milestone: Task) => void` | After milestone saved (add or edit) | Triggered after saving milestone via built-in MilestoneDialog. **Note**: Component has auto-updated `milestones` data, external only needs to listen to this event for additional processing (like calling API to save) |
| `milestone-deleted` | `{ milestoneId: number }` | After milestone deleted | Triggered after deleting milestone via built-in MilestoneDialog. **Note**: Component has auto-updated `milestones` data, external only needs to listen to this event for additional processing | | `milestone-deleted` | `{ milestoneId: number }` | After milestone deleted | Triggered after deleting milestone via built-in MilestoneDialog. **Note**: Component has auto-updated `milestones` data, external only needs to listen to this event for additional processing |
@@ -769,6 +775,7 @@ Milestones are used to mark important time points in a project, such as project
| `milestone-drag-end` | `(milestone: Task) => void` | When milestone drag ends | Milestone date updated. **Note**: Component has auto-updated `milestones` data | | `milestone-drag-end` | `(milestone: Task) => void` | When milestone drag ends | Milestone date updated. **Note**: Component has auto-updated `milestones` data |
**Data Synchronization Notes**: **Data Synchronization Notes**:
-**Component auto-updates internally**: For all milestone CRUD operations, component will auto-update `props.milestones` data -**Component auto-updates internally**: For all milestone CRUD operations, component will auto-update `props.milestones` data
-**Events are for notification only**: External event listeners are mainly for: showing messages, calling backend APIs, updating other related data, etc. -**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 `milestones` data again in event handlers, otherwise it will cause duplicate updates -**Avoid duplicate operations**: Don't modify `milestones` data again in event handlers, otherwise it will cause duplicate updates
@@ -805,15 +812,15 @@ const milestones = ref<Task[]>([
type: 'milestone', type: 'milestone',
icon: 'diamond', icon: 'diamond',
assignee: 'Project Manager', assignee: 'Project Manager',
description: 'Official project kickoff' description: 'Official project kickoff',
}, },
{ {
id: 102, id: 102,
name: 'Requirements Review', name: 'Requirements Review',
startDate: '2025-01-15', startDate: '2025-01-15',
type: 'milestone', type: 'milestone',
icon: 'flag' icon: 'flag',
} },
]) ])
// Toolbar "Add Milestone" button click event // Toolbar "Add Milestone" button click event
@@ -896,8 +903,8 @@ const milestones = ref<Task[]>([
type: 'milestone', type: 'milestone',
icon: 'diamond', icon: 'diamond',
assignee: 'Project Manager', assignee: 'Project Manager',
description: 'Official project kickoff' description: 'Official project kickoff',
} },
]) ])
const customDialogVisible = ref(false) const customDialogVisible = ref(false)
@@ -927,7 +934,7 @@ const handleCustomDialogSave = (milestone: Task) => {
const newMilestone = { const newMilestone = {
...milestone, ...milestone,
id: Date.now(), // Generate new ID id: Date.now(), // Generate new ID
type: 'milestone' type: 'milestone',
} }
milestones.value.push(newMilestone) milestones.value.push(newMilestone)
@@ -1028,9 +1035,7 @@ const handleMilestoneDrag = (milestone: Task) => {
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button v-if="!isNew" type="danger" @click="handleDelete"> <el-button v-if="!isNew" type="danger" @click="handleDelete"> Delete </el-button>
Delete
</el-button>
<el-button @click="handleClose">Cancel</el-button> <el-button @click="handleClose">Cancel</el-button>
<el-button type="primary" @click="handleSave">Save</el-button> <el-button type="primary" @click="handleSave">Save</el-button>
</div> </div>
@@ -1063,10 +1068,12 @@ const form = ref({
assignee: '', assignee: '',
icon: 'diamond', icon: 'diamond',
description: '', description: '',
type: 'milestone' type: 'milestone',
}) })
watch(() => props.visible, (val) => { watch(
() => props.visible,
val => {
dialogVisible.value = val dialogVisible.value = val
if (val) { if (val) {
if (props.milestone) { if (props.milestone) {
@@ -1081,13 +1088,14 @@ watch(() => props.visible, (val) => {
assignee: '', assignee: '',
icon: 'diamond', icon: 'diamond',
description: '', description: '',
type: 'milestone' type: 'milestone',
} }
} }
} }
}) }
)
watch(dialogVisible, (val) => { watch(dialogVisible, val => {
emit('update:visible', val) emit('update:visible', val)
}) })
@@ -1112,6 +1120,7 @@ const handleDelete = () => {
``` ```
> **💡 Custom Dialog Notes**: > **💡 Custom Dialog Notes**:
>
> - Set `use-default-milestone-dialog="false"` to disable built-in dialog > - Set `use-default-milestone-dialog="false"` to disable built-in dialog
> - Listen to `@add-milestone` event to open custom dialog > - Listen to `@add-milestone` event to open custom dialog
> - Need to manually manage `milestones` array CRUD operations > - Need to manually manage `milestones` array CRUD operations
@@ -1133,7 +1142,7 @@ Customize the toolbar functional buttons and time scale options.
**Type Definition:** **Type Definition:**
| Field | Type | Default | Description | | Field | Type | Default | Description |
|-------|------|---------|-------------| | --------------------- | ----------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `showAddTask` | `boolean` | `true` | Show "Add Task" button | | `showAddTask` | `boolean` | `true` | Show "Add Task" button |
| `showAddMilestone` | `boolean` | `true` | Show "Add Milestone" button | | `showAddMilestone` | `boolean` | `true` | Show "Add Milestone" button |
| `showTodayLocate` | `boolean` | `true` | Show "Locate to Today" button | | `showTodayLocate` | `boolean` | `true` | Show "Locate to Today" button |
@@ -1167,10 +1176,7 @@ TimelineScale.YEAR // 'year' - Year view
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :toolbar-config="toolbarConfig" />
:tasks="tasks"
:toolbar-config="toolbarConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1188,11 +1194,17 @@ const toolbarConfig: ToolbarConfig = {
showTheme: true, // Show theme switch button showTheme: true, // Show theme switch button
showFullscreen: true, // Show fullscreen button showFullscreen: true, // Show fullscreen button
showTimeScale: true, // Show time scale button group showTimeScale: true, // Show time scale button group
timeScaleDimensions: [ // Show all time scale dimensions timeScaleDimensions: [
'hour', 'day', 'week', 'month', 'quarter', 'year' // Show all time scale dimensions
'hour',
'day',
'week',
'month',
'quarter',
'year',
], ],
defaultTimeScale: 'week', // Default week view defaultTimeScale: 'week', // Default week view
showExpandCollapse: true // Show expand/collapse button showExpandCollapse: true, // Show expand/collapse button
} }
</script> </script>
``` ```
@@ -1213,11 +1225,14 @@ const toolbarConfig: ToolbarConfig = {
showTheme: true, // Keep theme switch showTheme: true, // Keep theme switch
showFullscreen: true, // Keep fullscreen showFullscreen: true, // Keep fullscreen
showTimeScale: true, // Show time scale showTimeScale: true, // Show time scale
timeScaleDimensions: [ // Only show day/week/month scales timeScaleDimensions: [
'day', 'week', 'month' // Only show day/week/month scales
'day',
'week',
'month',
], ],
defaultTimeScale: 'week', // Default week view defaultTimeScale: 'week', // Default week view
showExpandCollapse: true // Keep expand/collapse showExpandCollapse: true, // Keep expand/collapse
} }
</script> </script>
``` ```
@@ -1235,9 +1250,9 @@ const toolbarConfig: ToolbarConfig = {
TimelineScale.DAY, TimelineScale.DAY,
TimelineScale.WEEK, TimelineScale.WEEK,
TimelineScale.MONTH, TimelineScale.MONTH,
TimelineScale.QUARTER TimelineScale.QUARTER,
], ],
defaultTimeScale: TimelineScale.MONTH // Default month view defaultTimeScale: TimelineScale.MONTH, // Default month view
} }
</script> </script>
``` ```
@@ -1260,12 +1275,13 @@ const toolbarConfig: ToolbarConfig = {
showTimeScale: true, // Keep time scale switch showTimeScale: true, // Keep time scale switch
timeScaleDimensions: ['week', 'month'], timeScaleDimensions: ['week', 'month'],
defaultTimeScale: 'month', defaultTimeScale: 'month',
showExpandCollapse: false // Hide expand/collapse showExpandCollapse: false, // Hide expand/collapse
} }
</script> </script>
``` ```
> **💡 Configuration Recommendations** > **💡 Configuration Recommendations**
>
> - **Default configuration**When not passed, all buttons are shown by default > - **Default configuration**When not passed, all buttons are shown by default
> - **Show as needed**: Hide unnecessary feature buttons based on business requirements > - **Show as needed**: Hide unnecessary feature buttons based on business requirements
> - **Time scale**`timeScaleDimensions` controls which time dimensions to display, recommend selecting 2-4 common dimensions > - **Time scale**`timeScaleDimensions` controls which time dimensions to display, recommend selecting 2-4 common dimensions
@@ -1278,7 +1294,7 @@ Customize task list display columns, width limits, etc. Task list is located on
**Type Definition** **Type Definition**
| Field | Type | Default | Description | | Field | Type | Default | Description |
|--------|------|--------|------| | ---------------- | ------------------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------- |
| `columns` | `TaskListColumnConfig[]` | Default 8 columns | Task list column configuration array, defines which columns to display and their properties | | `columns` | `TaskListColumnConfig[]` | Default 8 columns | Task list column configuration array, defines which columns to display and their properties |
| `showAllColumns` | `boolean` | `true` | Whether to show all columns. When `true`, ignores `visible` setting in `columns` | | `showAllColumns` | `boolean` | `true` | Whether to show all columns. When `true`, ignores `visible` setting in `columns` |
| `defaultWidth` | `number \| string` | `320` | Default expanded width. Supports pixel number (like `320`) or percentage string (like `'30%'`) | | `defaultWidth` | `number \| string` | `320` | Default expanded width. Supports pixel number (like `320`) or percentage string (like `'30%'`) |
@@ -1288,7 +1304,7 @@ Customize task list display columns, width limits, etc. Task list is located on
**TaskListColumnConfig Type Definition** **TaskListColumnConfig Type Definition**
| Field | Type | Required | Description | | Field | Type | Required | Description |
|--------|------|------|------| | ---------- | --------- | -------- | ----------------------------------------------------------------------------------------------- |
| `key` | `string` | ✅ | Unique column identifier, used to access fields in Task object and for internationalization | | `key` | `string` | ✅ | Unique column identifier, used to access fields in Task object and for internationalization |
| `label` | `string` | - | Column display label (header text) | | `label` | `string` | - | Column display label (header text) |
| `cssClass` | `string` | - | Custom CSS class name | | `cssClass` | `string` | - | Custom CSS class name |
@@ -1299,10 +1315,7 @@ Customize task list display columns, width limits, etc. Task list is located on
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
:tasks="tasks"
:task-list-config="taskListConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1322,10 +1335,7 @@ const taskListConfig: TaskListConfig = {
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
:tasks="tasks"
:task-list-config="taskListConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1347,10 +1357,7 @@ Based on business requirements, you can customize columns to display, column wid
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
:tasks="tasks"
:task-list-config="taskListConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1435,10 +1442,7 @@ Combine `ref` and `computed` to achieve dynamic show/hide and width adjustment o
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
:tasks="tasks"
:task-list-config="taskListConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1477,6 +1481,7 @@ const taskListConfig = computed<TaskListConfig>(() => ({
``` ```
> **💡 Configuration Notes** > **💡 Configuration Notes**
>
> - **Default behavior**When not passed, show all 8 default columns with width of 320px > - **Default behavior**When not passed, show all 8 default columns with width of 320px
> - **Width units**Supports pixel (`number`) and percentage (`string`, like `'30%'`) methods > - **Width units**Supports pixel (`number`) and percentage (`string`, like `'30%'`) methods
> - **Percentage calculation**Based on total width of Gantt chart container, responsive adjustment > - **Percentage calculation**Based on total width of Gantt chart container, responsive adjustment
@@ -1493,7 +1498,7 @@ Controls task bar display content and interaction behavior。
**Configuration Fields** **Configuration Fields**
| Field | Type | Default | Description | | Field | Type | Default | Description |
|--------|------|--------|------| | ------------------- | --------- | ------- | --------------------------------------------------------- |
| `showAvatar` | `boolean` | `true` | Whether to show avatar | | `showAvatar` | `boolean` | `true` | Whether to show avatar |
| `showTitle` | `boolean` | `true` | Whether to show title text | | `showTitle` | `boolean` | `true` | Whether to show title text |
| `showProgress` | `boolean` | `true` | Whether to show progress text | | `showProgress` | `boolean` | `true` | Whether to show progress text |
@@ -1503,6 +1508,7 @@ Controls task bar display content and interaction behavior。
| `dragDelayTime` | `number` | `150` | Drag delay time (milliseconds) | | `dragDelayTime` | `number` | `150` | Drag delay time (milliseconds) |
> **💡 Edit Permission Control** > **💡 Edit Permission Control**
>
> - **Global control**: Use `<GanttChart :allow-drag-and-resize="false" />` to disable drag/resize for all tasks > - **Global control**: Use `<GanttChart :allow-drag-and-resize="false" />` to disable drag/resize for all tasks
> - **Individual task control**: Set task object `isEditable: false` property to control individual task > - **Individual task control**: Set task object `isEditable: false` property to control individual task
@@ -1510,10 +1516,7 @@ Controls task bar display content and interaction behavior。
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-bar-config="taskBarConfig" />
:tasks="tasks"
:task-bar-config="taskBarConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1539,10 +1542,7 @@ Disable edit operations for all tasks.
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :allow-drag-and-resize="false" />
:tasks="tasks"
:allow-drag-and-resize="false"
/>
</template> </template>
``` ```
@@ -1608,6 +1608,7 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
})) }))
</script> </script>
``` ```
#### Timeline Container Auto-Fill Configuration #### Timeline Container Auto-Fill Configuration
The component has built-in intelligent timeline range calculation logic, ensuring that regardless of task data volume or task duration, the timeline always fills the container width, providing the best visual experience. The component has built-in intelligent timeline range calculation logic, ensuring that regardless of task data volume or task duration, the timeline always fills the container width, providing the best visual experience.
@@ -1615,6 +1616,7 @@ The component has built-in intelligent timeline range calculation logic, ensurin
**Core Design Principles:** **Core Design Principles:**
1. **Base Buffer Mechanism**: Add fixed buffers based on the actual time range of tasks, varying by view type 1. **Base Buffer Mechanism**: Add fixed buffers based on the actual time range of tasks, varying by view type
- Hour view:±1 day task range - Hour view:±1 day task range
- Day view: ±30 days before/after task range - Day view: ±30 days before/after task range
- Week view: ±8 weeks (approx. 2 months) before/after task range - Week view: ±8 weeks (approx. 2 months) before/after task range
@@ -1623,10 +1625,12 @@ The component has built-in intelligent timeline range calculation logic, ensurin
- Year view: ±1 year before/after task range - Year view: ±1 year before/after task range
2. **Container Width Adaptation**: After base buffering, if calculated timeline width is less than container width, automatically extend the range 2. **Container Width Adaptation**: After base buffering, if calculated timeline width is less than container width, automatically extend the range
- Calculate time units (days/weeks/months/quarters/years) needed for container - Calculate time units (days/weeks/months/quarters/years) needed for container
- **Symmetrically extend** on both sides of base range to ensure timeline fills container - **Symmetrically extend** on both sides of base range to ensure timeline fills container
3. **Empty Data Handling**: When no task data exists, calculate reasonable time range based on container width and time scale 3. **Empty Data Handling**: When no task data exists, calculate reasonable time range based on container width and time scale
- Center on current date - Center on current date
- Dynamically calculate time span to display based on container width - Dynamically calculate time span to display based on container width
- Ensure minimum display range (e.g., at least 60 days for day view, at least 20 weeks for week view) - Ensure minimum display range (e.g., at least 60 days for day view, at least 20 weeks for week view)
@@ -1638,7 +1642,7 @@ The component has built-in intelligent timeline range calculation logic, ensurin
**Calculation Pattern Reference Table:** **Calculation Pattern Reference Table:**
| View | Unit Width | Base Buffer | Empty Data Min Range | Container Auto-Fill? | | View | Unit Width | Base Buffer | Empty Data Min Range | Container Auto-Fill? |
|------|-----------|--------------|----------------------|----------------| | ------------ | ------------------------- | ----------- | -------------------- | -------------------- |
| Hour View | 30px/hour | ±1 day | 3 days | ✅ | | Hour View | 30px/hour | ±1 day | 3 days | ✅ |
| Day View | 30px/day | ±30 days | 60 days | ✅ | | Day View | 30px/day | ±30 days | 60 days | ✅ |
| Week View | 60px/week | ±2 months | 20 weeks | ✅ | | Week View | 60px/week | ±2 months | 20 weeks | ✅ |
@@ -1649,11 +1653,13 @@ The component has built-in intelligent timeline range calculation logic, ensurin
**Practical Application Scenarios:** **Practical Application Scenarios:**
- **Short-term Tasks** (e.g., 1-week project): - **Short-term Tasks** (e.g., 1-week project):
- Won't result in narrow timeline, automatically extends to fill container - Won't result in narrow timeline, automatically extends to fill container
- Day view: 1 week (7 days × 30px = 210px) → Extends to ≥1200px (approx. 40 days) - Day view: 1 week (7 days × 30px = 210px) → Extends to ≥1200px (approx. 40 days)
- Week view: 1 week (60px) → Extends to ≥1200px (approx. 20 weeks) - Week view: 1 week (60px) → Extends to ≥1200px (approx. 20 weeks)
- **Long-term Projects** (e.g., 2-year project): - **Long-term Projects** (e.g., 2-year project):
- After adding fixed buffer, automatically adapts to container - After adding fixed buffer, automatically adapts to container
- Month view: 24 months + buffer → Extends to container width if needed - Month view: 24 months + buffer → Extends to container width if needed
- Quarter view: 8 quarters + buffer → Extends to container width if needed - Quarter view: 8 quarters + buffer → Extends to container width if needed
@@ -1665,6 +1671,7 @@ The component has built-in intelligent timeline range calculation logic, ensurin
- Quarter/Year view: Displays at least 5 years - Quarter/Year view: Displays at least 5 years
> **💡 Automation Advantages**: > **💡 Automation Advantages**:
>
> - No need to manually set `startDate` and `endDate`, component automatically calculates optimal range > - No need to manually set `startDate` and `endDate`, component automatically calculates optimal range
> - Responsive to container width changes, timeline automatically recalculates > - Responsive to container width changes, timeline automatically recalculates
> - Different views independently optimized, auto-adjusts to best display effect when switching views > - Different views independently optimized, auto-adjusts to best display effect when switching views
@@ -1679,10 +1686,7 @@ Component has built-in light and dark themes, can switch via toolbar button, als
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :on-theme-change="handleThemeChange" />
:tasks="tasks"
:on-theme-change="handleThemeChange"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1751,10 +1755,7 @@ Component has built-in Chinese (zh-CN) and English (en-US), can switch via toolb
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :on-language-change="handleLanguageChange" />
:tasks="tasks"
:on-language-change="handleLanguageChange"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1772,10 +1773,7 @@ Override or extend default translations via `localeMessages` prop:
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :locale-messages="customMessages" />
:tasks="tasks"
:locale-messages="customMessages"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1832,6 +1830,7 @@ const customMessages = {
``` ```
> **💡 Tip** > **💡 Tip**
>
> - `localeMessages` adopts **deep merge** strategy, only need to pass fields that need to be overridden > - `localeMessages` adopts **deep merge** strategy, only need to pass fields that need to be overridden
> - supports nested objects, like `taskList.name`, `toolbar.addTask`, etc. > - supports nested objects, like `taskList.name`, `toolbar.addTask`, etc.
> - For complete translation keys, please refer to built-in `messages['zh-CN']` object in component > - For complete translation keys, please refer to built-in `messages['zh-CN']` object in component
@@ -1849,14 +1848,14 @@ Used to customize task display content in task list (TaskRow) and timeline (Task
**Slot Parameters** **Slot Parameters**
| Parameter | Type | Source | Description | | Parameter | Type | Source | Description |
|--------|------|------|------| | --------- | ---------------------------- | ------ | ----------------------------- |
| `type` | `'task-row'` \| `'task-bar'` | Common | Slot call position identifier | | `type` | `'task-row'` \| `'task-bar'` | Common | Slot call position identifier |
| `task` | `Task` | Common | Current task object | | `task` | `Task` | Common | Current task object |
**TaskRow specific parameters (when `type === 'task-row'`):** **TaskRow specific parameters (when `type === 'task-row'`):**
| Parameter | Type | Description | | Parameter | Type | Description |
|--------|------|------| | ---------------- | -------------------------------- | ------------------------- |
| `isRowContent` | `boolean` | Identified as row content | | `isRowContent` | `boolean` | Identified as row content |
| `level` | `number` | Task level | | `level` | `number` | Task level |
| `indent` | `string` | Indent style | | `indent` | `string` | Indent style |
@@ -1878,7 +1877,7 @@ Used to customize task display content in task list (TaskRow) and timeline (Task
**TaskBar specific parameters (when `type === 'task-bar'`):** **TaskBar specific parameters (when `type === 'task-bar'`):**
| Parameter | Type | Description | | Parameter | Type | Description |
|--------|------|------| | ------------------ | --------------- | ------------------------------------------------------------------------------------ |
| `status` | `object` | TaskStatus object, contains `type`, `color`, `bgColor`, `borderColor` | | `status` | `object` | TaskStatus object, contains `type`, `color`, `bgColor`, `borderColor` |
| `statusType` | `string` | StatusType`'completed'`, `'delayed'`, `'in-progress'`, `'not-started'`, `'parent'` | | `statusType` | `string` | StatusType`'completed'`, `'delayed'`, `'in-progress'`, `'not-started'`, `'parent'` |
| `isParent` | `boolean` | Whether parent task | | `isParent` | `boolean` | Whether parent task |
@@ -1894,11 +1893,7 @@ Used to customize task display content in task list (TaskRow) and timeline (Task
<GanttChart :tasks="tasks"> <GanttChart :tasks="tasks">
<template #custom-task-content="slotProps"> <template #custom-task-content="slotProps">
<!-- Render different content based on type --> <!-- Render different content based on type -->
<CustomTaskContent <CustomTaskContent :task="slotProps.task" :type="slotProps.type" :status="slotProps.status" />
:task="slotProps.task"
:type="slotProps.type"
:status="slotProps.status"
/>
</template> </template>
</GanttChart> </GanttChart>
</template> </template>
@@ -1916,8 +1911,8 @@ const tasks = ref<Task[]>([
name: '<strong>Important Task</strong>', name: '<strong>Important Task</strong>',
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 50 progress: 50,
} },
]) ])
</script> </script>
``` ```
@@ -1994,6 +1989,7 @@ const props = defineProps<Props>()
``` ```
> **💡 Usage Scenarios** > **💡 Usage Scenarios**
>
> - Support HTML formatted task names > - Support HTML formatted task names
> - Add custom icons, tags or badges > - Add custom icons, tags or badges
> - Display different styles based on task status > - Display different styles based on task status
@@ -2001,6 +1997,7 @@ const props = defineProps<Props>()
> - Display additional business information > - Display additional business information
> **⚠️ Notes** > **⚠️ Notes**
>
> - Slot content will be rendered in both TaskRow and TaskBar > - Slot content will be rendered in both TaskRow and TaskBar
> - Need to distinguish rendering position based on `type` parameter > - Need to distinguish rendering position based on `type` parameter
> - TaskRow and TaskBar have different available space, need to adapt layout > - TaskRow and TaskBar have different available space, need to adapt layout
+120 -129
View File
@@ -2,7 +2,10 @@
<p align="center"> <p align="center">
<a href="https://www.npmjs.com/package/jordium-gantt-vue3"> <a href="https://www.npmjs.com/package/jordium-gantt-vue3">
<img src="https://img.shields.io/npm/v/jordium-gantt-vue3.svg" alt="npm version"> <img src="https://img.shields.io/npm/v/jordium-gantt-vue3?style=flat-square" alt="npm version">
</a>
<a href="https://www.npmjs.com/package/jordium-gantt-vue3">
<img src="https://img.shields.io/npm/dt/jordium-gantt-vue3?style=flat-square" alt="npm total">
</a> </a>
<a href="https://opensource.org/licenses/MIT"> <a href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"> <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License">
@@ -105,10 +108,7 @@ import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
```vue ```vue
<template> <template>
<div style="height: 600px;"> <div style="height: 600px;">
<GanttChart <GanttChart :tasks="tasks" :milestones="milestones" />
:tasks="tasks"
:milestones="milestones"
/>
</div> </div>
</template> </template>
@@ -123,7 +123,7 @@ const tasks = ref([
name: '项目启动', name: '项目启动',
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 100 progress: 100,
}, },
{ {
id: 2, id: 2,
@@ -131,7 +131,7 @@ const tasks = ref([
startDate: '2025-01-11', startDate: '2025-01-11',
endDate: '2025-01-20', endDate: '2025-01-20',
progress: 80, progress: 80,
predecessor: [1] predecessor: [1],
}, },
{ {
id: 3, id: 3,
@@ -139,8 +139,8 @@ const tasks = ref([
startDate: '2025-01-21', startDate: '2025-01-21',
endDate: '2025-02-05', endDate: '2025-02-05',
progress: 50, progress: 50,
predecessor: [2] predecessor: [2],
} },
]) ])
const milestones = ref([ const milestones = ref([
@@ -148,8 +148,8 @@ const milestones = ref([
id: 101, id: 101,
name: '项目立项', name: '项目立项',
date: '2025-01-01', date: '2025-01-01',
type: 'milestone' type: 'milestone',
} },
]) ])
</script> </script>
``` ```
@@ -158,6 +158,7 @@ const milestones = ref([
<span><strong>推荐使用 <a href="https://dovee.cc/a.php?anaxjgyz1ozZq2B">DOVE</a> VPN,快速、稳定。</strong></span> <span style="color:red;">(注意:请合法使用 VPN 资源)</span> <span><strong>推荐使用 <a href="https://dovee.cc/a.php?anaxjgyz1ozZq2B">DOVE</a> VPN,快速、稳定。</strong></span> <span style="color:red;">(注意:请合法使用 VPN 资源)</span>
## 🌞 NPM包使用示例 ## 🌞 NPM包使用示例
请参考项目下的npm-demo,这是一个独立的项目,可以使用IDE单独浏览和启动,运行前请安装element plus以及jordium-gantt-vue3插件包 请参考项目下的npm-demo,这是一个独立的项目,可以使用IDE单独浏览和启动,运行前请安装element plus以及jordium-gantt-vue3插件包
```bash ```bash
@@ -166,6 +167,7 @@ npm install element-plus
npm install jordium-gantt-vue3 npm install jordium-gantt-vue3
npm run dev npm run dev
``` ```
--- ---
## 组件指南 ## 组件指南
@@ -177,7 +179,7 @@ npm run dev
#### 基础属性 #### 基础属性
| 属性名 | 类型 | 默认值 | 说明 | | 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------| | --------------------------- | --------- | ------- | -------------------------------------------------------------- |
| `tasks` | `Task[]` | `[]` | 任务数据数组 | | `tasks` | `Task[]` | `[]` | 任务数据数组 |
| `milestones` | `Task[]` | `[]` | 里程碑数据数组(注意:类型为 Task[],需设置 type='milestone' | | `milestones` | `Task[]` | `[]` | 里程碑数据数组(注意:类型为 Task[],需设置 type='milestone' |
| `showToolbar` | `boolean` | `true` | 是否显示工具栏 | | `showToolbar` | `boolean` | `true` | 是否显示工具栏 |
@@ -191,7 +193,7 @@ npm run dev
完整的配置对象说明请参考 [⚙️ 配置与扩展](#⚙️-配置与扩展) 章节。 完整的配置对象说明请参考 [⚙️ 配置与扩展](#⚙️-配置与扩展) 章节。
| 属性名 | 类型 | 默认值 | 说明 | | 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------| | ---------------- | ---------------------------- | ----------------------------------------------------------------------- | ---------------- |
| `toolbarConfig` | `ToolbarConfig` | `{}` | 工具栏配置 | | `toolbarConfig` | `ToolbarConfig` | `{}` | 工具栏配置 |
| `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置 | | `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置 |
| `taskBarConfig` | `TaskBarConfig` | `undefined` | 任务条样式配置 | | `taskBarConfig` | `TaskBarConfig` | `undefined` | 任务条样式配置 |
@@ -201,7 +203,7 @@ npm run dev
#### 回调函数属性 #### 回调函数属性
| 属性名 | 类型 | 说明 | | 属性名 | 类型 | 说明 |
|--------|------|------| | -------------------- | ------------------------------------ | -------------------------------------------------------- |
| `onTodayLocate` | `() => void` | 工具栏"今天"按钮点击回调 | | `onTodayLocate` | `() => void` | 工具栏"今天"按钮点击回调 |
| `onExportCsv` | `() => boolean \| void` | 工具栏"导出CSV"按钮点击回调,返回 `false` 可阻止默认导出 | | `onExportCsv` | `() => boolean \| void` | 工具栏"导出CSV"按钮点击回调,返回 `false` 可阻止默认导出 |
| `onExportPdf` | `() => void` | 工具栏"导出PDF"按钮点击回调 | | `onExportPdf` | `() => void` | 工具栏"导出PDF"按钮点击回调 |
@@ -214,13 +216,14 @@ npm run dev
#### 组件事件(Events #### 组件事件(Events
完整的事件说明请分别参考: 完整的事件说明请分别参考:
- **任务相关事件**:参见下方 [任务管理](#任务管理) 章节 - **任务相关事件**:参见下方 [任务管理](#任务管理) 章节
- **里程碑相关事件**:参见下方 [里程碑管理](#里程碑管理) 章节 - **里程碑相关事件**:参见下方 [里程碑管理](#里程碑管理) 章节
**事件列表总览:** **事件列表总览:**
| 事件名 | 参数 | 说明 | | 事件名 | 参数 | 说明 |
|--------|------|------| | ------------------------ | --------------------------------- | -------------------------- |
| `add-task` | - | 点击工具栏"添加任务"按钮 | | `add-task` | - | 点击工具栏"添加任务"按钮 |
| `task-click` | `(task: Task, event: MouseEvent)` | 点击任务 | | `task-click` | `(task: Task, event: MouseEvent)` | 点击任务 |
| `task-double-click` | `(task: Task)` | 双击任务 | | `task-double-click` | `(task: Task)` | 双击任务 |
@@ -259,8 +262,8 @@ const tasks = ref([
name: '任务1', name: '任务1',
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 100 progress: 100,
} },
]) ])
</script> </script>
``` ```
@@ -270,10 +273,7 @@ const tasks = ref([
```vue ```vue
<template> <template>
<div style="height: 600px;"> <div style="height: 600px;">
<GanttChart <GanttChart :tasks="tasks" :milestones="milestones" />
:tasks="tasks"
:milestones="milestones"
/>
</div> </div>
</template> </template>
@@ -288,8 +288,8 @@ const tasks = ref([
name: '项目启动', name: '项目启动',
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 100 progress: 100,
} },
]) ])
const milestones = ref([ const milestones = ref([
@@ -298,8 +298,8 @@ const milestones = ref([
name: '项目立项', name: '项目立项',
startDate: '2025-01-01', startDate: '2025-01-01',
type: 'milestone', type: 'milestone',
icon: 'diamond' icon: 'diamond',
} },
]) ])
</script> </script>
``` ```
@@ -342,7 +342,7 @@ const addTask = () => {
name: '新任务', name: '新任务',
startDate: new Date().toISOString().split('T')[0], startDate: new Date().toISOString().split('T')[0],
endDate: new Date().toISOString().split('T')[0], endDate: new Date().toISOString().split('T')[0],
progress: 0 progress: 0,
} }
tasks.value.push(newTask) tasks.value.push(newTask)
} }
@@ -352,16 +352,16 @@ const addMilestone = () => {
id: Date.now(), id: Date.now(),
name: '新里程碑', name: '新里程碑',
startDate: new Date().toISOString().split('T')[0], startDate: new Date().toISOString().split('T')[0],
type: 'milestone' type: 'milestone',
} }
milestones.value.push(newMilestone) milestones.value.push(newMilestone)
} }
const handleTaskAdded = (e) => { const handleTaskAdded = e => {
console.log('任务已添加:', e.task) console.log('任务已添加:', e.task)
} }
const handleMilestoneSaved = (milestone) => { const handleMilestoneSaved = milestone => {
console.log('里程碑已保存:', milestone) console.log('里程碑已保存:', milestone)
} }
</script> </script>
@@ -376,7 +376,7 @@ const handleMilestoneSaved = (milestone) => {
#### Task 数据结构 #### Task 数据结构
| 字段名 | 类型 | 必填 | 默认值 | 说明 | | 字段名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------| | ------------------ | ---------- | ---- | ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `id` | `number` | ✅ | - | 任务唯一标识符 | | `id` | `number` | ✅ | - | 任务唯一标识符 |
| `name` | `string` | ✅ | - | 任务名称 | | `name` | `string` | ✅ | - | 任务名称 |
| `startDate` | `string` | - | - | 开始日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' | | `startDate` | `string` | - | - | 开始日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
@@ -406,6 +406,7 @@ const handleMilestoneSaved = (milestone) => {
> **自定义属性扩展**:Task 接口支持添加任意自定义字段,例如:`priority`、`tags`、`status`、`department` 等业务相关字段。 > **自定义属性扩展**:Task 接口支持添加任意自定义字段,例如:`priority`、`tags`、`status`、`department` 等业务相关字段。
> >
> **前置任务字段说明** > **前置任务字段说明**
>
> - **标准格式**(推荐):`predecessor: [1, 2, 3]` - number 数组 > - **标准格式**(推荐):`predecessor: [1, 2, 3]` - number 数组
> - **兼容格式1**`predecessor: '1,2,3'` - 逗号分隔的字符串 > - **兼容格式1**`predecessor: '1,2,3'` - 逗号分隔的字符串
> - **兼容格式2**`predecessor: ['1', '2', '3']` - 字符串数组 > - **兼容格式2**`predecessor: ['1', '2', '3']` - 字符串数组
@@ -415,7 +416,7 @@ const handleMilestoneSaved = (milestone) => {
#### 任务相关属性 #### 任务相关属性
| 属性名 | 类型 | 默认值 | 说明 | | 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------| | --------------------- | ---------------- | ----------- | -------------------------------------------------------------- |
| `tasks` | `Task[]` | `[]` | 任务数据数组 | | `tasks` | `Task[]` | `[]` | 任务数据数组 |
| `useDefaultDrawer` | `boolean` | `true` | 是否使用内置的任务编辑抽屉(TaskDrawer) | | `useDefaultDrawer` | `boolean` | `true` | 是否使用内置的任务编辑抽屉(TaskDrawer) |
| `taskBarConfig` | `TaskBarConfig` | `{}` | 任务条样式配置,详见 [TaskBarConfig 配置](#taskbarconfig-配置) | | `taskBarConfig` | `TaskBarConfig` | `{}` | 任务条样式配置,详见 [TaskBarConfig 配置](#taskbarconfig-配置) |
@@ -423,6 +424,7 @@ const handleMilestoneSaved = (milestone) => {
| `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 | | `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 |
**配置说明** **配置说明**
- **默认模式**`useDefaultDrawer=true`(默认),双击任务自动打开内置 TaskDrawer - **默认模式**`useDefaultDrawer=true`(默认),双击任务自动打开内置 TaskDrawer
- **自定义编辑器**`useDefaultDrawer=false` 禁用内置抽屉,监听 `@task-double-click` 事件打开自定义编辑器 - **自定义编辑器**`useDefaultDrawer=false` 禁用内置抽屉,监听 `@task-double-click` 事件打开自定义编辑器
- **只读模式**`useDefaultDrawer=false` 且不监听 `@task-double-click` 事件,用户双击任务无反应 - **只读模式**`useDefaultDrawer=false` 且不监听 `@task-double-click` 事件,用户双击任务无反应
@@ -432,7 +434,7 @@ const handleMilestoneSaved = (milestone) => {
> **💡 事件驱动架构**:组件采用纯事件驱动设计,所有用户操作(添加、编辑、删除、拖拽等)都会触发对应事件,方便外部监听和处理。 > **💡 事件驱动架构**:组件采用纯事件驱动设计,所有用户操作(添加、编辑、删除、拖拽等)都会触发对应事件,方便外部监听和处理。
| 事件名 | 参数 | 触发时机 | 说明 | | 事件名 | 参数 | 触发时机 | 说明 |
|--------|------|---------|------| | -------------------- | ----------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `add-task` | - | 点击工具栏"添加任务"按钮时 | 可用于自定义新增任务逻辑。如 `useDefaultDrawer=true`,组件会自动打开内置 TaskDrawer | | `add-task` | - | 点击工具栏"添加任务"按钮时 | 可用于自定义新增任务逻辑。如 `useDefaultDrawer=true`,组件会自动打开内置 TaskDrawer |
| `task-click` | `(task: Task, event: MouseEvent) => void` | 点击任务条时 | 单击任务触发 | | `task-click` | `(task: Task, event: MouseEvent) => void` | 点击任务条时 | 单击任务触发 |
| `task-double-click` | `(task: Task) => void` | 双击任务条时 | 双击任务时**始终触发**。`useDefaultDrawer=true` 时组件会额外打开内置编辑器,`false` 时不打开。事件触发与属性值无关 | | `task-double-click` | `(task: Task) => void` | 双击任务条时 | 双击任务时**始终触发**。`useDefaultDrawer=true` 时组件会额外打开内置编辑器,`false` 时不打开。事件触发与属性值无关 |
@@ -447,6 +449,7 @@ const handleMilestoneSaved = (milestone) => {
| `timer-stopped` | `(task: Task) => void` | 任务计时器停止时 | 停止记录任务工时 | | `timer-stopped` | `(task: Task) => void` | 任务计时器停止时 | 停止记录任务工时 |
**数据同步说明** **数据同步说明**
-**组件内部自动更新**:所有任务的增删改操作,组件都会自动更新 `props.tasks` 数据 -**组件内部自动更新**:所有任务的增删改操作,组件都会自动更新 `props.tasks` 数据
-**事件仅做通知**:外部监听事件主要用于:显示提示消息、调用后端 API、更新其他相关数据等 -**事件仅做通知**:外部监听事件主要用于:显示提示消息、调用后端 API、更新其他相关数据等
-**避免重复操作**:不要在事件处理器中再次修改 `tasks` 数据,否则会导致重复更新 -**避免重复操作**:不要在事件处理器中再次修改 `tasks` 数据,否则会导致重复更新
@@ -492,7 +495,7 @@ const tasks = ref<Task[]>([
progress: 60, progress: 60,
assignee: '李四', assignee: '李四',
predecessor: [1], // 依赖任务1 predecessor: [1], // 依赖任务1
} },
]) ])
// 工具栏"添加任务"按钮点击事件 // 工具栏"添加任务"按钮点击事件
@@ -565,7 +568,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 100, progress: 100,
predecessor: [] // 无前置任务 predecessor: [], // 无前置任务
}, },
{ {
id: 2, id: 2,
@@ -573,7 +576,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-11', startDate: '2025-01-11',
endDate: '2025-01-20', endDate: '2025-01-20',
progress: 80, progress: 80,
predecessor: [1] // 依赖任务1(需求分析) predecessor: [1], // 依赖任务1(需求分析)
}, },
{ {
id: 3, id: 3,
@@ -581,7 +584,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-11', startDate: '2025-01-11',
endDate: '2025-01-18', endDate: '2025-01-18',
progress: 90, progress: 90,
predecessor: [1] // 依赖任务1 predecessor: [1], // 依赖任务1
}, },
{ {
id: 4, id: 4,
@@ -589,7 +592,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-21', startDate: '2025-01-21',
endDate: '2025-02-10', endDate: '2025-02-10',
progress: 60, progress: 60,
predecessor: [2] // 依赖任务2(系统设计) predecessor: [2], // 依赖任务2(系统设计)
}, },
{ {
id: 5, id: 5,
@@ -597,7 +600,7 @@ const tasks = ref<Task[]>([
startDate: '2025-01-19', startDate: '2025-01-19',
endDate: '2025-02-08', endDate: '2025-02-08',
progress: 70, progress: 70,
predecessor: [2, 3] // 同时依赖任务2和3 predecessor: [2, 3], // 同时依赖任务2和3
}, },
{ {
id: 6, id: 6,
@@ -605,8 +608,8 @@ const tasks = ref<Task[]>([
startDate: '2025-02-11', startDate: '2025-02-11',
endDate: '2025-02-20', endDate: '2025-02-20',
progress: 30, progress: 30,
predecessor: [4, 5] // 依赖前端和后端开发完成 predecessor: [4, 5], // 依赖前端和后端开发完成
} },
]) ])
// 通过右键菜单添加前置任务时触发 // 通过右键菜单添加前置任务时触发
@@ -628,6 +631,7 @@ const handleSuccessorAdded = (event: { targetTask: Task; newTask: Task }) => {
``` ```
**依赖关系说明** **依赖关系说明**
- **`predecessor` 字段支持多种格式** - **`predecessor` 字段支持多种格式**
- 标准格式(推荐):`[1, 2, 3]` - number 数组 - 标准格式(推荐):`[1, 2, 3]` - number 数组
- 兼容格式1`'1,2,3'` - 逗号分隔的字符串 - 兼容格式1`'1,2,3'` - 逗号分隔的字符串
@@ -696,7 +700,7 @@ const handleAddMilestone = () => {
console.log('准备新增里程碑(由自定义按钮触发)') console.log('准备新增里程碑(由自定义按钮触发)')
} }
const handleTaskAdded = (e) => { const handleTaskAdded = e => {
console.log('任务已添加:', e.task) console.log('任务已添加:', e.task)
// 调用 API 保存... // 调用 API 保存...
} }
@@ -704,6 +708,7 @@ const handleTaskAdded = (e) => {
``` ```
> **💡 灵活性设计** > **💡 灵活性设计**
>
> - 显示工具栏 + 默认编辑器:最简单的开箱即用方式 > - 显示工具栏 + 默认编辑器:最简单的开箱即用方式
> - 隐藏工具栏 + 自定义按钮 + 默认编辑器:自定义控制栏样式,保留默认编辑功能 > - 隐藏工具栏 + 自定义按钮 + 默认编辑器:自定义控制栏样式,保留默认编辑功能
> - 隐藏工具栏 + 自定义按钮 + 自定义编辑器:完全自定义所有交互逻辑 > - 隐藏工具栏 + 自定义按钮 + 自定义编辑器:完全自定义所有交互逻辑
@@ -717,7 +722,7 @@ const handleTaskAdded = (e) => {
#### Milestone 数据结构 #### Milestone 数据结构
| 字段名 | 类型 | 必填 | 默认值 | 说明 | | 字段名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------| | ------------- | -------- | ---- | ------------- | ---------------------------------------------------------- |
| `id` | `number` | ✅ | - | 里程碑唯一标识符 | | `id` | `number` | ✅ | - | 里程碑唯一标识符 |
| `name` | `string` | ✅ | - | 里程碑名称 | | `name` | `string` | ✅ | - | 里程碑名称 |
| `startDate` | `string` | ✅ | - | 里程碑日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' | | `startDate` | `string` | ✅ | - | 里程碑日期,格式:'YYYY-MM-DD' 或 'YYYY-MM-DD HH:mm' |
@@ -732,16 +737,18 @@ const handleTaskAdded = (e) => {
#### 里程碑相关属性 #### 里程碑相关属性
| 属性名 | 类型 | 默认值 | 说明 | | 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------| | --------------------------- | --------- | ------ | -------------------------------------------------------- |
| `milestones` | `Task[]` | `[]` | 里程碑数据数组(类型为 Task[],需确保 type='milestone' | | `milestones` | `Task[]` | `[]` | 里程碑数据数组(类型为 Task[],需确保 type='milestone' |
| `useDefaultMilestoneDialog` | `boolean` | `true` | 是否使用内置的里程碑编辑对话框(MilestoneDialog | | `useDefaultMilestoneDialog` | `boolean` | `true` | 是否使用内置的里程碑编辑对话框(MilestoneDialog |
**配置说明** **配置说明**
- **默认模式**`useDefaultMilestoneDialog=true`(默认),双击里程碑自动打开内置 MilestoneDialog - **默认模式**`useDefaultMilestoneDialog=true`(默认),双击里程碑自动打开内置 MilestoneDialog
- **禁用编辑器**`useDefaultMilestoneDialog=false`,双击里程碑无反应(组件不打开任何编辑器) - **禁用编辑器**`useDefaultMilestoneDialog=false`,双击里程碑无反应(组件不打开任何编辑器)
- **自定义编辑器**:可以监听 `onMilestoneDoubleClick` 回调或相关事件,实现自定义编辑逻辑 - **自定义编辑器**:可以监听 `onMilestoneDoubleClick` 回调或相关事件,实现自定义编辑逻辑
> **💡 里程碑与任务的区别** > **💡 里程碑与任务的区别**
>
> - 里程碑数据通过 `milestones` 属性独立管理,与 `tasks` 分开 > - 里程碑数据通过 `milestones` 属性独立管理,与 `tasks` 分开
> - 里程碑对象的 `type` 字段必须设置为 `'milestone'` > - 里程碑对象的 `type` 字段必须设置为 `'milestone'`
> - 里程碑不支持子任务、依赖关系等复杂结构 > - 里程碑不支持子任务、依赖关系等复杂结构
@@ -751,13 +758,12 @@ const handleTaskAdded = (e) => {
> **⚠️ 已废弃**:请使用新的事件驱动 API(见下方"里程碑事件"章节) > **⚠️ 已废弃**:请使用新的事件驱动 API(见下方"里程碑事件"章节)
#### 里程碑事件 #### 里程碑事件
> **💡 事件驱动架构**:里程碑管理采用事件驱动设计,推荐使用事件 API 替代回调函数。 > **💡 事件驱动架构**:里程碑管理采用事件驱动设计,推荐使用事件 API 替代回调函数。
| 事件名 | 参数 | 触发时机 | 说明 | | 事件名 | 参数 | 触发时机 | 说明 |
|--------|------|---------|------| | ------------------------ | --------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `add-milestone` | - | 点击工具栏"添加里程碑"按钮时 | 可用于自定义新增里程碑逻辑。如 `useDefaultMilestoneDialog=true`,组件会自动打开内置 MilestoneDialog | | `add-milestone` | - | 点击工具栏"添加里程碑"按钮时 | 可用于自定义新增里程碑逻辑。如 `useDefaultMilestoneDialog=true`,组件会自动打开内置 MilestoneDialog |
| `milestone-saved` | `(milestone: Task) => void` | 里程碑保存后(新增或编辑) | 通过内置 MilestoneDialog 保存里程碑后触发。**注意**:组件已自动更新 `milestones` 数据,外部只需监听此事件做额外处理(如调用 API 保存) | | `milestone-saved` | `(milestone: Task) => void` | 里程碑保存后(新增或编辑) | 通过内置 MilestoneDialog 保存里程碑后触发。**注意**:组件已自动更新 `milestones` 数据,外部只需监听此事件做额外处理(如调用 API 保存) |
| `milestone-deleted` | `{ milestoneId: number }` | 里程碑删除后 | 通过内置 MilestoneDialog 删除里程碑后触发。**注意**:组件已自动更新 `milestones` 数据,外部只需监听此事件做额外处理 | | `milestone-deleted` | `{ milestoneId: number }` | 里程碑删除后 | 通过内置 MilestoneDialog 删除里程碑后触发。**注意**:组件已自动更新 `milestones` 数据,外部只需监听此事件做额外处理 |
@@ -765,6 +771,7 @@ const handleTaskAdded = (e) => {
| `milestone-drag-end` | `(milestone: Task) => void` | 拖拽里程碑结束时 | 里程碑日期已更新。**注意**:组件已自动更新 `milestones` 数据 | | `milestone-drag-end` | `(milestone: Task) => void` | 拖拽里程碑结束时 | 里程碑日期已更新。**注意**:组件已自动更新 `milestones` 数据 |
**数据同步说明** **数据同步说明**
-**组件内部自动更新**:所有里程碑的增删改操作,组件都会自动更新 `props.milestones` 数据 -**组件内部自动更新**:所有里程碑的增删改操作,组件都会自动更新 `props.milestones` 数据
-**事件仅做通知**:外部监听事件主要用于:显示提示消息、调用后端 API、更新其他相关数据等 -**事件仅做通知**:外部监听事件主要用于:显示提示消息、调用后端 API、更新其他相关数据等
-**避免重复操作**:不要在事件处理器中再次修改 `milestones` 数据,否则会导致重复更新 -**避免重复操作**:不要在事件处理器中再次修改 `milestones` 数据,否则会导致重复更新
@@ -801,15 +808,15 @@ const milestones = ref<Task[]>([
type: 'milestone', type: 'milestone',
icon: 'diamond', icon: 'diamond',
assignee: '项目经理', assignee: '项目经理',
description: '项目正式启动' description: '项目正式启动',
}, },
{ {
id: 102, id: 102,
name: '需求评审', name: '需求评审',
startDate: '2025-01-15', startDate: '2025-01-15',
type: 'milestone', type: 'milestone',
icon: 'flag' icon: 'flag',
} },
]) ])
// 工具栏"添加里程碑"按钮点击事件 // 工具栏"添加里程碑"按钮点击事件
@@ -892,8 +899,8 @@ const milestones = ref<Task[]>([
type: 'milestone', type: 'milestone',
icon: 'diamond', icon: 'diamond',
assignee: '项目经理', assignee: '项目经理',
description: '项目正式启动' description: '项目正式启动',
} },
]) ])
const customDialogVisible = ref(false) const customDialogVisible = ref(false)
@@ -923,7 +930,7 @@ const handleCustomDialogSave = (milestone: Task) => {
const newMilestone = { const newMilestone = {
...milestone, ...milestone,
id: Date.now(), // 生成新 ID id: Date.now(), // 生成新 ID
type: 'milestone' type: 'milestone',
} }
milestones.value.push(newMilestone) milestones.value.push(newMilestone)
@@ -1013,20 +1020,13 @@ const handleMilestoneDrag = (milestone: Task) => {
</el-form-item> </el-form-item>
<el-form-item label="描述"> <el-form-item label="描述">
<el-input <el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入描述" />
v-model="form.description"
type="textarea"
:rows="3"
placeholder="请输入描述"
/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button v-if="!isNew" type="danger" @click="handleDelete"> <el-button v-if="!isNew" type="danger" @click="handleDelete"> 删除 </el-button>
删除
</el-button>
<el-button @click="handleClose">取消</el-button> <el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleSave">保存</el-button> <el-button type="primary" @click="handleSave">保存</el-button>
</div> </div>
@@ -1059,10 +1059,12 @@ const form = ref({
assignee: '', assignee: '',
icon: 'diamond', icon: 'diamond',
description: '', description: '',
type: 'milestone' type: 'milestone',
}) })
watch(() => props.visible, (val) => { watch(
() => props.visible,
val => {
dialogVisible.value = val dialogVisible.value = val
if (val) { if (val) {
if (props.milestone) { if (props.milestone) {
@@ -1077,13 +1079,14 @@ watch(() => props.visible, (val) => {
assignee: '', assignee: '',
icon: 'diamond', icon: 'diamond',
description: '', description: '',
type: 'milestone' type: 'milestone',
} }
} }
} }
}) }
)
watch(dialogVisible, (val) => { watch(dialogVisible, val => {
emit('update:visible', val) emit('update:visible', val)
}) })
@@ -1108,6 +1111,7 @@ const handleDelete = () => {
``` ```
> **💡 自定义对话框说明** > **💡 自定义对话框说明**
>
> - 设置 `use-default-milestone-dialog="false"` 禁用内置对话框 > - 设置 `use-default-milestone-dialog="false"` 禁用内置对话框
> - 监听 `@add-milestone` 事件打开自定义对话框 > - 监听 `@add-milestone` 事件打开自定义对话框
> - 需要手动管理 `milestones` 数组的增删改 > - 需要手动管理 `milestones` 数组的增删改
@@ -1129,7 +1133,7 @@ const handleDelete = () => {
**类型定义:** **类型定义:**
| 字段名 | 类型 | 默认值 | 说明 | | 字段名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------| | --------------------- | ----------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `showAddTask` | `boolean` | `true` | 显示"添加任务"按钮 | | `showAddTask` | `boolean` | `true` | 显示"添加任务"按钮 |
| `showAddMilestone` | `boolean` | `true` | 显示"添加里程碑"按钮 | | `showAddMilestone` | `boolean` | `true` | 显示"添加里程碑"按钮 |
| `showTodayLocate` | `boolean` | `true` | 显示"定位到今天"按钮 | | `showTodayLocate` | `boolean` | `true` | 显示"定位到今天"按钮 |
@@ -1163,10 +1167,7 @@ TimelineScale.YEAR // 'year' - 年视图
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :toolbar-config="toolbarConfig" />
:tasks="tasks"
:toolbar-config="toolbarConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1184,11 +1185,17 @@ const toolbarConfig: ToolbarConfig = {
showTheme: true, // 显示主题切换按钮 showTheme: true, // 显示主题切换按钮
showFullscreen: true, // 显示全屏按钮 showFullscreen: true, // 显示全屏按钮
showTimeScale: true, // 显示时间刻度按钮组 showTimeScale: true, // 显示时间刻度按钮组
timeScaleDimensions: [ // 显示所有时间刻度维度 timeScaleDimensions: [
'hour', 'day', 'week', 'month', 'quarter', 'year' // 显示所有时间刻度维度
'hour',
'day',
'week',
'month',
'quarter',
'year',
], ],
defaultTimeScale: 'week', // 默认选中周视图 defaultTimeScale: 'week', // 默认选中周视图
showExpandCollapse: true // 显示展开/折叠按钮 showExpandCollapse: true, // 显示展开/折叠按钮
} }
</script> </script>
``` ```
@@ -1209,11 +1216,14 @@ const toolbarConfig: ToolbarConfig = {
showTheme: true, // 保留主题切换 showTheme: true, // 保留主题切换
showFullscreen: true, // 保留全屏 showFullscreen: true, // 保留全屏
showTimeScale: true, // 显示时间刻度 showTimeScale: true, // 显示时间刻度
timeScaleDimensions: [ // 只显示日/周/月三种刻度 timeScaleDimensions: [
'day', 'week', 'month' // 只显示日/周/月三种刻度
'day',
'week',
'month',
], ],
defaultTimeScale: 'week', // 默认周视图 defaultTimeScale: 'week', // 默认周视图
showExpandCollapse: true // 保留展开/折叠 showExpandCollapse: true, // 保留展开/折叠
} }
</script> </script>
``` ```
@@ -1231,9 +1241,9 @@ const toolbarConfig: ToolbarConfig = {
TimelineScale.DAY, TimelineScale.DAY,
TimelineScale.WEEK, TimelineScale.WEEK,
TimelineScale.MONTH, TimelineScale.MONTH,
TimelineScale.QUARTER TimelineScale.QUARTER,
], ],
defaultTimeScale: TimelineScale.MONTH // 默认月视图 defaultTimeScale: TimelineScale.MONTH, // 默认月视图
} }
</script> </script>
``` ```
@@ -1256,12 +1266,13 @@ const toolbarConfig: ToolbarConfig = {
showTimeScale: true, // 保留时间刻度切换 showTimeScale: true, // 保留时间刻度切换
timeScaleDimensions: ['week', 'month'], timeScaleDimensions: ['week', 'month'],
defaultTimeScale: 'month', defaultTimeScale: 'month',
showExpandCollapse: false // 隐藏展开/折叠 showExpandCollapse: false, // 隐藏展开/折叠
} }
</script> </script>
``` ```
> **💡 配置建议** > **💡 配置建议**
>
> - **默认配置**:不传 `toolbar-config` 时,所有按钮默认显示 > - **默认配置**:不传 `toolbar-config` 时,所有按钮默认显示
> - **按需显示**:根据业务需求隐藏不需要的功能按钮 > - **按需显示**:根据业务需求隐藏不需要的功能按钮
> - **时间刻度**`timeScaleDimensions` 控制显示哪些时间维度,建议选择 2-4 个常用维度 > - **时间刻度**`timeScaleDimensions` 控制显示哪些时间维度,建议选择 2-4 个常用维度
@@ -1274,7 +1285,7 @@ const toolbarConfig: ToolbarConfig = {
**类型定义:** **类型定义:**
| 字段名 | 类型 | 默认值 | 说明 | | 字段名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------| | ---------------- | ------------------------ | ------- | ------------------------------------------------------------------------------ |
| `columns` | `TaskListColumnConfig[]` | 默认8列 | 任务列表的列配置数组,定义显示哪些列及其属性 | | `columns` | `TaskListColumnConfig[]` | 默认8列 | 任务列表的列配置数组,定义显示哪些列及其属性 |
| `showAllColumns` | `boolean` | `true` | 是否显示所有列。`true` 时忽略 `columns` 中的 `visible` 设置 | | `showAllColumns` | `boolean` | `true` | 是否显示所有列。`true` 时忽略 `columns` 中的 `visible` 设置 |
| `defaultWidth` | `number \| string` | `320` | 默认展开宽度。支持像素数字(如 `320`)或百分比字符串(如 `'30%'` | | `defaultWidth` | `number \| string` | `320` | 默认展开宽度。支持像素数字(如 `320`)或百分比字符串(如 `'30%'` |
@@ -1284,7 +1295,7 @@ const toolbarConfig: ToolbarConfig = {
**TaskListColumnConfig 类型定义:** **TaskListColumnConfig 类型定义:**
| 字段名 | 类型 | 必填 | 说明 | | 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------| | ---------- | --------- | ---- | ---------------------------------------------------------------- |
| `key` | `string` | ✅ | 列的唯一标识符,用于访问 Task 对象中的字段,也用于国际化 | | `key` | `string` | ✅ | 列的唯一标识符,用于访问 Task 对象中的字段,也用于国际化 |
| `label` | `string` | - | 列的显示标签(表头文字) | | `label` | `string` | - | 列的显示标签(表头文字) |
| `cssClass` | `string` | - | 自定义 CSS 类名 | | `cssClass` | `string` | - | 自定义 CSS 类名 |
@@ -1295,10 +1306,7 @@ const toolbarConfig: ToolbarConfig = {
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
:tasks="tasks"
:task-list-config="taskListConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1318,10 +1326,7 @@ const taskListConfig: TaskListConfig = {
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
:tasks="tasks"
:task-list-config="taskListConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1343,10 +1348,7 @@ const taskListConfig: TaskListConfig = {
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
:tasks="tasks"
:task-list-config="taskListConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1431,10 +1433,7 @@ const taskListConfig: TaskListConfig = {
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-list-config="taskListConfig" />
:tasks="tasks"
:task-list-config="taskListConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1473,6 +1472,7 @@ const taskListConfig = computed<TaskListConfig>(() => ({
``` ```
> **💡 配置说明** > **💡 配置说明**
>
> - **默认行为**:不传 `task-list-config` 时,显示所有 8 个默认列,宽度为 320px > - **默认行为**:不传 `task-list-config` 时,显示所有 8 个默认列,宽度为 320px
> - **宽度单位**:支持像素(`number`)和百分比(`string`,如 `'30%'`)两种方式 > - **宽度单位**:支持像素(`number`)和百分比(`string`,如 `'30%'`)两种方式
> - **百分比计算**:基于甘特图容器的总宽度,响应式调整 > - **百分比计算**:基于甘特图容器的总宽度,响应式调整
@@ -1489,7 +1489,7 @@ const taskListConfig = computed<TaskListConfig>(() => ({
**配置字段:** **配置字段:**
| 字段名 | 类型 | 默认值 | 说明 | | 字段名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------| | ------------------- | --------- | ------- | ------------------------------- |
| `showAvatar` | `boolean` | `true` | 是否展示头像 | | `showAvatar` | `boolean` | `true` | 是否展示头像 |
| `showTitle` | `boolean` | `true` | 是否展示标题文字 | | `showTitle` | `boolean` | `true` | 是否展示标题文字 |
| `showProgress` | `boolean` | `true` | 是否展示进度文字 | | `showProgress` | `boolean` | `true` | 是否展示进度文字 |
@@ -1499,6 +1499,7 @@ const taskListConfig = computed<TaskListConfig>(() => ({
| `dragDelayTime` | `number` | `150` | 拖拽延迟时间(毫秒) | | `dragDelayTime` | `number` | `150` | 拖拽延迟时间(毫秒) |
> **💡 编辑权限控制** > **💡 编辑权限控制**
>
> - **全局控制**:使用 `<GanttChart :allow-drag-and-resize="false" />` 禁用所有任务的拖拽/拉伸 > - **全局控制**:使用 `<GanttChart :allow-drag-and-resize="false" />` 禁用所有任务的拖拽/拉伸
> - **单个任务控制**:设置任务对象的 `isEditable: false` 属性单独控制某个任务 > - **单个任务控制**:设置任务对象的 `isEditable: false` 属性单独控制某个任务
@@ -1506,10 +1507,7 @@ const taskListConfig = computed<TaskListConfig>(() => ({
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :task-bar-config="taskBarConfig" />
:tasks="tasks"
:task-bar-config="taskBarConfig"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1535,10 +1533,7 @@ const taskBarConfig: TaskBarConfig = {
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :allow-drag-and-resize="false" />
:tasks="tasks"
:allow-drag-and-resize="false"
/>
</template> </template>
``` ```
@@ -1612,6 +1607,7 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
**核心设计思路:** **核心设计思路:**
1. **基础缓冲机制**:在任务的实际时间范围基础上,根据不同视图添加固定的缓冲区 1. **基础缓冲机制**:在任务的实际时间范围基础上,根据不同视图添加固定的缓冲区
- 小时视图:任务范围前后各 ±1 天 - 小时视图:任务范围前后各 ±1 天
- 日视图:任务范围前后各 ±30 天 - 日视图:任务范围前后各 ±30 天
- 周视图:任务范围前后各 ±8 周(约2个月) - 周视图:任务范围前后各 ±8 周(约2个月)
@@ -1620,10 +1616,12 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
- 年视图:任务范围前后各 ±1 年 - 年视图:任务范围前后各 ±1 年
2. **容器宽度适配**:基础缓冲后,如果计算出的时间线宽度小于容器宽度,会自动扩展范围 2. **容器宽度适配**:基础缓冲后,如果计算出的时间线宽度小于容器宽度,会自动扩展范围
- 计算容器需要的时间单位数(天/周/月/季度/年) - 计算容器需要的时间单位数(天/周/月/季度/年)
- 在基础范围两侧**对称扩展**,确保时间线填充满容器 - 在基础范围两侧**对称扩展**,确保时间线填充满容器
3. **空数据处理**:当没有任务数据时,根据容器宽度和时间刻度计算合理的时间范围 3. **空数据处理**:当没有任务数据时,根据容器宽度和时间刻度计算合理的时间范围
- 以当前日期为中心 - 以当前日期为中心
- 根据容器宽度动态计算需要显示的时间跨度 - 根据容器宽度动态计算需要显示的时间跨度
- 确保最小显示范围(如日视图至少60天,周视图至少20周等) - 确保最小显示范围(如日视图至少60天,周视图至少20周等)
@@ -1635,7 +1633,7 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
**各视图计算模式对照表:** **各视图计算模式对照表:**
| 视图 | 单位宽度 | 基础缓冲 | 空数据最小范围 | 容器自动填充? | | 视图 | 单位宽度 | 基础缓冲 | 空数据最小范围 | 容器自动填充? |
|------|----------|----------|----------------|----------| | -------- | -------------------- | -------- | -------------- | -------------- |
| 小时视图 | 30px/时 | ±1天 | 3天 | ✅ | | 小时视图 | 30px/时 | ±1天 | 3天 | ✅ |
| 日视图 | 30px/天 | ±30天 | 60天 | ✅ | | 日视图 | 30px/天 | ±30天 | 60天 | ✅ |
| 周视图 | 60px/周 | ±2月 | 20周 | ✅ | | 周视图 | 60px/周 | ±2月 | 20周 | ✅ |
@@ -1646,11 +1644,13 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
**实际应用场景:** **实际应用场景:**
- **短期任务**(如1周项目, 分辨率1080): - **短期任务**(如1周项目, 分辨率1080):
- 不会导致时间线过窄,自动扩展到填充满容器 - 不会导致时间线过窄,自动扩展到填充满容器
- 日视图:1周(7天×30px=210px) → 扩展至 ≥1200px(约40天) - 日视图:1周(7天×30px=210px) → 扩展至 ≥1200px(约40天)
- 周视图:1周(60px) → 扩展至 ≥1200px(约20周) - 周视图:1周(60px) → 扩展至 ≥1200px(约20周)
- **长期项目**(如2年项目): - **长期项目**(如2年项目):
- 添加固定缓冲后,自动适配容器 - 添加固定缓冲后,自动适配容器
- 月视图:24个月 + 缓冲 → 如需要则扩展至容器宽度 - 月视图:24个月 + 缓冲 → 如需要则扩展至容器宽度
- 季度视图:8个季度 + 缓冲 → 如需要则扩展至容器宽度 - 季度视图:8个季度 + 缓冲 → 如需要则扩展至容器宽度
@@ -1662,6 +1662,7 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
- 季度/年视图:显示至少5年 - 季度/年视图:显示至少5年
> **💡 自动化优势** > **💡 自动化优势**
>
> - 无需手动设置 `startDate` 和 `endDate`,组件会自动计算最优范围 > - 无需手动设置 `startDate` 和 `endDate`,组件会自动计算最优范围
> - 响应式容器宽度变化,时间线自动重新计算 > - 响应式容器宽度变化,时间线自动重新计算
> - 不同视图独立优化,切换视图时自动调整到最佳显示效果 > - 不同视图独立优化,切换视图时自动调整到最佳显示效果
@@ -1676,10 +1677,7 @@ const taskBarConfig = computed<TaskBarConfig>(() => ({
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :on-theme-change="handleThemeChange" />
:tasks="tasks"
:on-theme-change="handleThemeChange"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1748,10 +1746,7 @@ const handleThemeChange = (isDark: boolean) => {
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :on-language-change="handleLanguageChange" />
:tasks="tasks"
:on-language-change="handleLanguageChange"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1769,10 +1764,7 @@ const handleLanguageChange = (lang: 'zh-CN' | 'en-US') => {
```vue ```vue
<template> <template>
<GanttChart <GanttChart :tasks="tasks" :locale-messages="customMessages" />
:tasks="tasks"
:locale-messages="customMessages"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1829,6 +1821,7 @@ const customMessages = {
``` ```
> **💡 提示** > **💡 提示**
>
> - `localeMessages` 采用**深度合并**策略,只需传递需要覆盖的字段即可 > - `localeMessages` 采用**深度合并**策略,只需传递需要覆盖的字段即可
> - 支持嵌套对象,如 `taskList.name`、`toolbar.addTask` 等 > - 支持嵌套对象,如 `taskList.name`、`toolbar.addTask` 等
> - 完整的翻译键请参考组件内置的 `messages['zh-CN']` 对象 > - 完整的翻译键请参考组件内置的 `messages['zh-CN']` 对象
@@ -1846,14 +1839,14 @@ const customMessages = {
**插槽参数:** **插槽参数:**
| 参数名 | 类型 | 来源 | 说明 | | 参数名 | 类型 | 来源 | 说明 |
|--------|------|------|------| | ------ | ---------------------------- | ---- | ---------------- |
| `type` | `'task-row'` \| `'task-bar'` | 通用 | 插槽调用位置标识 | | `type` | `'task-row'` \| `'task-bar'` | 通用 | 插槽调用位置标识 |
| `task` | `Task` | 通用 | 当前任务对象 | | `task` | `Task` | 通用 | 当前任务对象 |
**TaskRow 特有参数(当 `type === 'task-row'` 时):** **TaskRow 特有参数(当 `type === 'task-row'` 时):**
| 参数名 | 类型 | 说明 | | 参数名 | 类型 | 说明 |
|--------|------|------| | ---------------- | -------------------------------- | ---------------- |
| `isRowContent` | `boolean` | 标识为行内容 | | `isRowContent` | `boolean` | 标识为行内容 |
| `level` | `number` | 任务层级 | | `level` | `number` | 任务层级 |
| `indent` | `string` | 缩进样式 | | `indent` | `string` | 缩进样式 |
@@ -1875,7 +1868,7 @@ const customMessages = {
**TaskBar 特有参数(当 `type === 'task-bar'` 时):** **TaskBar 特有参数(当 `type === 'task-bar'` 时):**
| 参数名 | 类型 | 说明 | | 参数名 | 类型 | 说明 |
|--------|------|------| | ------------------ | --------------- | ---------------------------------------------------------------------------------- |
| `status` | `object` | 任务状态对象,包含 `type`, `color`, `bgColor`, `borderColor` | | `status` | `object` | 任务状态对象,包含 `type`, `color`, `bgColor`, `borderColor` |
| `statusType` | `string` | 状态类型:`'completed'`, `'delayed'`, `'in-progress'`, `'not-started'`, `'parent'` | | `statusType` | `string` | 状态类型:`'completed'`, `'delayed'`, `'in-progress'`, `'not-started'`, `'parent'` |
| `isParent` | `boolean` | 是否为父任务 | | `isParent` | `boolean` | 是否为父任务 |
@@ -1891,11 +1884,7 @@ const customMessages = {
<GanttChart :tasks="tasks"> <GanttChart :tasks="tasks">
<template #custom-task-content="slotProps"> <template #custom-task-content="slotProps">
<!-- 根据类型渲染不同内容 --> <!-- 根据类型渲染不同内容 -->
<CustomTaskContent <CustomTaskContent :task="slotProps.task" :type="slotProps.type" :status="slotProps.status" />
:task="slotProps.task"
:type="slotProps.type"
:status="slotProps.status"
/>
</template> </template>
</GanttChart> </GanttChart>
</template> </template>
@@ -1913,8 +1902,8 @@ const tasks = ref<Task[]>([
name: '<strong>重要任务</strong>', name: '<strong>重要任务</strong>',
startDate: '2025-01-01', startDate: '2025-01-01',
endDate: '2025-01-10', endDate: '2025-01-10',
progress: 50 progress: 50,
} },
]) ])
</script> </script>
``` ```
@@ -1991,6 +1980,7 @@ const props = defineProps<Props>()
``` ```
> **💡 使用场景** > **💡 使用场景**
>
> - 支持 HTML 格式的任务名称 > - 支持 HTML 格式的任务名称
> - 添加自定义图标、标签或徽章 > - 添加自定义图标、标签或徽章
> - 根据任务状态显示不同样式 > - 根据任务状态显示不同样式
@@ -1998,6 +1988,7 @@ const props = defineProps<Props>()
> - 显示额外的业务信息 > - 显示额外的业务信息
> **⚠️ 注意事项** > **⚠️ 注意事项**
>
> - 插槽内容会同时在 TaskRow 和 TaskBar 中渲染 > - 插槽内容会同时在 TaskRow 和 TaskBar 中渲染
> - 需要根据 `type` 参数区分渲染位置 > - 需要根据 `type` 参数区分渲染位置
> - TaskRow 和 TaskBar 的可用空间不同,需要适配布局 > - TaskRow 和 TaskBar 的可用空间不同,需要适配布局