From c7ea67b4cc1b92fc887a8a76c950b2bba0b81414 Mon Sep 17 00:00:00 2001 From: "LINING-PC\\lining" Date: Sun, 14 Dec 2025 16:06:44 +0800 Subject: [PATCH] =?UTF-8?q?v1.6.0=20-=20=E6=8F=90=E4=BE=9BTask=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=8F=92=E6=A7=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 18 ++ README-EN.md | 322 ++++++++++++++++++++++++ README.md | 324 +++++++++++++++++++++++- demo/App.vue | 87 ++++--- demo/DeclarativeColumnsDemo.vue | 347 -------------------------- demo/version-history.json | 20 ++ package.json | 2 +- scripts/generate-css-export.js | 2 +- src/components/GanttConfirmDialog.vue | 2 +- src/components/GanttToolbar.vue | 1 + src/components/TaskList.vue | 37 +-- src/components/TaskListColumn.vue | 2 +- src/components/TaskRow.vue | 26 +- src/composables/useI18n.ts | 10 +- vite.config.lib.ts | 2 +- 15 files changed, 788 insertions(+), 414 deletions(-) delete mode 100644 demo/DeclarativeColumnsDemo.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index f0653dc..846afb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.6.0] - 2025-12-14 + +### Added +- 🎉 新增:Task Table列声明式定义方式, 使用组件TaskListColumn +- 🎉 新增:Task Table #header和#default Slots +- 🎉 新增:Task List行样式设置属性 - task-list-row-class-name和task-list-row-style +- 🎉 新增:为兼容旧版本TaskListColumnConfig,提供task-list-column-render-mode属性开关,可以通过设置选择Task表格列定义方式 +- 🎉 Added: Declarative definition method for Task Table columns using the TaskListColumn component +- 🎉 Added: Task Table #header and #default Slots +- 🎉 Added: Task List row style setting properties - task-list-row-class-name and task-list-row-style +- 🎉 Added: A switch for task-list-column-render-mode attribute to choose Task Table column definition method for compatibility with older versions of TaskListColumnConfig + +### Fixed +- 🔧 修复:仅删除Story层级后,子Task升级后关系线丢失问题 +- 🔧 修复:修复已知问题 +- 🔧 Fixed: Issue of missing relationship lines after upgrading child Tasks when only deleting Story +- 🔧 Fixed: Fixed issues + ## [1.5.0] - 2025-12-13 ### Added diff --git a/README-EN.md b/README-EN.md index c893f90..c19113f 100644 --- a/README-EN.md +++ b/README-EN.md @@ -193,6 +193,39 @@ npm run dev | `enableTaskRowMove` | `boolean` | `false` | Whether to allow dragging and dropping TaskRow | | `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | Assignee dropdown options in task edit drawer | +#### TaskListColumn Component Props + +The `TaskListColumn` component is used to define task list columns in declarative mode (`taskListColumnRenderMode="declarative"`). Similar to Element Plus's `el-table-column` component. + +| Prop | Type | Default | Description | +| ---------- | ------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `prop` | `string` | - | Column property name, used to access task object fields. Examples: `'name'`, `'assignee'`, `'progress'`, etc. | +| `label` | `string` | - | Column header display text | +| `width` | `number \| string` | - | Column width. Number represents pixels (e.g., `200`), string supports percentage (e.g., `'20%'`) | +| `align` | `'left' \| 'center' \| 'right'` | `'left'` | Column content alignment | +| `cssClass` | `string` | - | Custom CSS class name for column styling | + +**Usage Example**: + +```vue + + + + + + + +``` + +> **💡 Tips**: +> - The `TaskListColumn` component itself does not render any content, it only declares column configuration +> - Must be used inside the `GanttChart` component with `task-list-column-render-mode="declarative"` set +> - Column display order is determined by the declaration order of `TaskListColumn` components +> - For detailed column content customization and slot usage, see [Slots](#slots) section + #### Configuration Object Props For complete configuration object documentation, see [⚙️ Configuration & Customization](#⚙️-configuration--customization) section. @@ -450,6 +483,9 @@ Tasks are the core elements of the Gantt chart. The component provides complete | `autoSortByStartDate` | `boolean` | `false` | Whether to automatically sort tasks by start date | | `enableTaskRowMove` | `boolean` | `false` | Whether to alloww dragging and dropping TaskRow | | `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | Assignee dropdown options in task edit drawer | +| `taskListColumnRenderMode` | `'default' \| 'declarative'` | `'default'` | Task list column render mode. `'default'`: Use TaskListColumnConfig configuration (compatibility mode, will be gradually deprecated); `'declarative'`: Use TaskListColumn component for declarative column definition (recommended). See [TaskListColumn Declarative Column Definition](#tasklistcolumn-declarative-column-definition) | +| `taskListRowClassName` | `string \| ((task: Task) => string)` | `undefined` | Custom CSS class name for task rows. Can be a string or a function that returns a string. **Note**: Row height is managed internally by the component, custom height styles will not take effect | +| `taskListRowStyle` | `CSSProperties \| ((task: Task) => CSSProperties)` | `undefined` | Custom inline styles for task rows. Can be a style object or a function that returns a style object. **Note**: Row height and width are managed internally by the component, custom width/height styles will not take effect | **Configuration Notes**: @@ -2221,6 +2257,292 @@ const props = defineProps() > - TaskRow and TaskBar have different available space, need to adapt layout > - Avoid using overly complex components in slot content, may affect performance +##### TaskListColumn Slots + +The `TaskListColumn` component provides two slots for customizing task list column headers and cell content. Must be used in declarative mode (`taskListColumnRenderMode="declarative"`). + +**Slot List:** + +| Slot Name | Parameters | Description | +| --------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `header` | - | Custom column header content. If not provided, the `label` prop will be displayed | +| `default` | `scope: { row: Task, $index: number }` | Custom column cell content. Access current task object via `scope.row`, access task index via `scope.$index`. If not provided, the value of `prop` field is shown | + +**Usage Example:** + +```vue + + + +``` + +> **💡 Usage Scenarios**: +> +> - Custom column header icons, styles, or sorting buttons +> - Display visual components like progress bars, status badges +> - Dynamically adjust styles and content based on task data +> - Add action buttons (edit, delete, etc.) +> - Integrate third-party UI components (ratings, tag selectors, etc.) + +> **⚠️ Notes**: +> +> - Slots must be used in `task-list-column-render-mode="declarative"` mode +> - The `default` slot receives a `scope` parameter, access current task object via `scope.row` (Task type), access index via `scope.$index` +> - Recommended to use `scope.row` instead of destructuring `{ row }` for code clarity and consistency +> - `scope.$index` is the index of the current task in the visible list (not global index) +> - Slot content is rendered in each task row, avoid overly complex components for performance +> - When column width is fixed, slot content should consider overflow handling (text ellipsis, auto-wrap, etc.) + +##### TaskListColumnConfig Column Slots (Deprecated Soon) + +> **⚠️ Important Notice**: This slot approach based on `TaskListColumnConfig` configuration is **deprecated and will be removed soon**. Strongly recommend using the declarative approach with [TaskListColumn Slots](#tasklistcolumn-slots) above for better type hints and code maintainability. + +In default mode (`taskListColumnRenderMode="default"`), you can customize columns defined in `TaskListColumnConfig` via slots. Slot names are based on the `key` property in column configuration. + +**Slot List:** + +| Slot Pattern | Parameters | Description | +| --------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `header-{key}` | - | Custom header content for specified column. `{key}` is the `key` value defined in `TaskListColumnConfig` | +| `column-{key}` | `{ task: Task, column: TaskListColumnConfig, value: any }` | Custom cell content for specified column. `task` is current task object, `column` is column config, `value` is the column's value | + +**Usage Example:** + +```vue + + + +``` + +> **💡 Usage Notes**: +> +> - Slot name format: `header-{key}` and `column-{key}`, where `{key}` corresponds to `TaskListColumnConfig.key` +> - `column-{key}` slot receives three parameters: +> - `task`: Current task object (Task type) +> - `column`: Current column configuration object (TaskListColumnConfig type) +> - `value`: Current cell value (automatically obtained from `task[column.key]`) +> - You can mix slots and default rendering, only define slots for columns that need customization + +> **⚠️ Migration Recommendation**: +> +> - **Strongly recommend migrating to declarative mode**: Use `task-list-column-render-mode="declarative"` with `TaskListColumn` component +> - Declarative mode provides better type hints, code organization, and maintainability +> - This configuration-based slot approach will be removed in future versions, please migrate soon +> - For migration examples, see [TaskListColumn Slots](#tasklistcolumn-slots) section + --- ## ❓ FAQ diff --git a/README.md b/README.md index f610c51..b188d6f 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,39 @@ npm run dev | `enableTaskRowMove` | `boolean` | `false` | 是否允许拖拽和摆放TaskRow | | `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | 任务编辑抽屉中负责人下拉菜单的选项列表 | +#### TaskListColumn 属性 + +`TaskListColumn` 组件用于在声明式模式(`taskListColumnRenderMode="declarative"`)下定义任务列表的列。类似于 Element Plus 的 `el-table-column` 组件。 + +| 属性名 | 类型 | 默认值 | 说明 | +| ---------- | ------------------------------ | -------- | ---------------------------------------------------------------------------------------------------------- | +| `prop` | `string` | - | 列的属性名,用于访问任务对象的字段。例如:`'name'`、`'assignee'`、`'progress'` 等 | +| `label` | `string` | - | 列的显示标题文本 | +| `width` | `number \| string` | - | 列宽度。数字表示像素值(如 `200`),字符串支持百分比(如 `'20%'`) | +| `align` | `'left' \| 'center' \| 'right'` | `'left'` | 列内容对齐方式 | +| `cssClass` | `string` | - | 自定义 CSS 类名,用于列样式定制 | + +**使用示例**: + +```vue + + + + + + + +``` + +> **💡 提示**: +> - `TaskListColumn` 组件本身不渲染任何内容,仅用于声明列配置 +> - 必须在 `GanttChart` 组件内部使用,且设置 `task-list-column-render-mode="declarative"` +> - 列的显示顺序由 `TaskListColumn` 组件的声明顺序决定 +> - 关于列内容自定义和插槽的详细使用方法,请参考 [插槽 (Slots)](#插槽-slots) 章节 + #### 配置对象属性 完整的配置对象说明请参考 [⚙️ 配置与扩展](#⚙️-配置与扩展) 章节。 @@ -447,7 +480,10 @@ const handleMilestoneSaved = milestone => { | `taskListConfig` | `TaskListConfig` | `undefined` | 任务列表配置,详见 [TaskListConfig 配置](#tasklistconfig-配置) | | `autoSortByStartDate` | `boolean` | `false` | 是否根据开始时间自动排序任务 | | `enableTaskRowMove` | `boolean` | `false` | 是否允许拖拽和摆放TaskRow | -| `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | 任务编辑抽屉中负责人下拉菜单的选项列表 | +| `assigneeOptions` | `Array<{ key?: string \| number; value: string \| number; label: string }>` | `[]` | 任务编辑抽屉中负责人下拉菜单的选项列表 | +| `taskListColumnRenderMode` | `'default' \| 'declarative'` | `'default'` | 任务列表列渲染模式。`'default'`:使用 TaskListColumnConfig 配置(兼容模式,将逐渐废弃);`'declarative'`:使用 TaskListColumn 组件声明式定义列(推荐)。详见 [TaskListColumn 声明式列定义](#tasklistcolumn-声明式列定义) | +| `taskListRowClassName` | `string \| ((task: Task) => string)` | `undefined` | 自定义任务行的 CSS 类名。可以是字符串或返回字符串的函数。**注意**:行的高度由组件内部统一管理,自定义高度样式不会生效 | +| `taskListRowStyle` | `CSSProperties \| ((task: Task) => CSSProperties)` | `undefined` | 自定义任务行的内联样式。可以是样式对象或返回样式对象的函数。**注意**:行的高度和宽度由组件内部统一管理,自定义宽高样式不会生效 | **配置说明**: @@ -2212,6 +2248,292 @@ const props = defineProps() > - TaskRow 和 TaskBar 的可用空间不同,需要适配布局 > - 避免在插槽内容中使用过于复杂的组件,可能影响性能 +##### TaskListColumn 插槽 + +`TaskListColumn` 组件提供了两个插槽,用于自定义任务列表的列头和单元格内容。必须在声明式模式(`taskListColumnRenderMode="declarative"`)下使用。 + +**插槽列表:** + +| 插槽名 | 参数 | 说明 | +| --------- | --------------------------------- | ---------------------------------------------------------------------------------------------- | +| `header` | - | 自定义列表头内容。如果未提供此插槽,将显示 `label` 属性 | +| `default` | `scope: { row: Task, $index: number }` | 自定义列单元格内容。通过 `scope.row` 访问当前任务对象,通过 `scope.$index` 访问任务索引。如果未提供此插槽,将显示 `prop` 对应的字段值 | + +**使用示例:** + +```vue + + + +``` + +> **💡 使用场景**: +> +> - 自定义列表头图标、样式或排序按钮 +> - 显示进度条、状态标签等可视化组件 +> - 根据任务数据动态调整样式和内容 +> - 添加操作按钮(编辑、删除等) +> - 集成第三方UI组件(如评分、标签选择器等) + +> **⚠️ 注意事项**: +> +> - 插槽必须在 `task-list-column-render-mode="declarative"` 模式下使用 +> - `default` 插槽接收 `scope` 参数,通过 `scope.row` 访问当前任务对象(Task类型),通过 `scope.$index` 访问索引 +> - 推荐使用 `scope.row` 而不是解构 `{ row }`,以保持代码的清晰性和一致性 +> - `scope.$index` 为当前任务在可见列表中的索引(非全局索引) +> - 插槽内容会在每个任务行中渲染,避免过于复杂的组件以保证性能 +> - 列宽固定后,插槽内容应考虑溢出处理(如文本省略、自动换行等) + +##### TaskListColumnConfig 列插槽(即将废弃) + +> **⚠️ 重要提示**:此插槽方式基于 `TaskListColumnConfig` 配置,**即将废弃**。强烈建议使用上述 [TaskListColumn 插槽](#tasklistcolumn-插槽) 的声明式方式,以获得更好的类型提示和代码可维护性。 + +在默认模式(`taskListColumnRenderMode="default"`)下,可以通过插槽自定义 `TaskListColumnConfig` 中定义的列。插槽名称基于列配置中的 `key` 属性。 + +**插槽列表:** + +| 插槽名模式 | 参数 | 说明 | +| --------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| `header-{key}` | - | 自定义指定列的表头内容。`{key}` 为 `TaskListColumnConfig` 中定义的 `key` 值 | +| `column-{key}` | `{ task: Task, column: TaskListColumnConfig, value: any }` | 自定义指定列的单元格内容。`task` 为当前任务对象,`column` 为列配置,`value` 为该列的值 | + +**使用示例:** + +```vue + + + +``` + +> **💡 使用说明**: +> +> - 插槽名称格式:`header-{key}` 和 `column-{key}`,其中 `{key}` 对应 `TaskListColumnConfig.key` +> - `column-{key}` 插槽接收三个参数: +> - `task`:当前任务对象(Task类型) +> - `column`:当前列配置对象(TaskListColumnConfig类型) +> - `value`:当前单元格的值(自动从 `task[column.key]` 获取) +> - 可以混合使用插槽和默认渲染,只为需要自定义的列定义插槽 + +> **⚠️ 迁移建议**: +> +> - **强烈建议迁移到声明式模式**:使用 `task-list-column-render-mode="declarative"` 和 `TaskListColumn` 组件 +> - 声明式模式提供更好的类型提示、代码组织和可维护性 +> - 此配置式插槽方式将在未来版本中移除,请尽快迁移 +> - 迁移示例请参考 [TaskListColumn 插槽](#tasklistcolumn-插槽) 章节 + --- ## ❓ 常见问题 diff --git a/demo/App.vue b/demo/App.vue index 8c2d1c8..405cada 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -142,6 +142,9 @@ const toolbarConfig = { showExpandCollapse: true, // 显示全部展开/折叠按钮 } +// TaskList列渲染模式配置 +const taskListColumnRenderMode = ref<'default' | 'declarative'>('declarative') + // TaskList列配置 const availableColumns = ref([ { key: 'predecessor', label: '前置任务', visible: true }, @@ -518,6 +521,7 @@ const handleTaskAddEvent = (e: { task: Task }) => { // 任务删除事件处理器 const handleTaskDeleteEvent = (e: { task: Task; deleteChildren?: boolean }) => { const task = e.task + const deleteChildren = e.deleteChildren showMessage(`Demo 任务[${task.name}] 已删除`, 'success') @@ -525,8 +529,10 @@ const handleTaskDeleteEvent = (e: { task: Task; deleteChildren?: boolean }) => { // 这里只需要显示消息,无需再次执行删除逻辑 // 如果需要在删除后清理其他数据(如 predecessor),可以在这里处理 - // 收集被删除任务的所有ID(包括子任务) - const deletedTaskIds = collectAllTaskIds(task) + // 收集被删除任务的ID + // 如果 deleteChildren 为 false,只删除父任务本身,子任务会被提升,所以不应该收集子任务ID + // 如果 deleteChildren 为 true,删除父任务及所有子任务,需要收集所有ID + const deletedTaskIds = deleteChildren ? collectAllTaskIds(task) : [task.id] // 清理predecessor依赖关系 cleanupPredecessorReferences(deletedTaskIds) } @@ -749,13 +755,24 @@ const handleTaskRowMoved = async (payload: { }} @@ -998,6 +1015,25 @@ const handleTaskRowMoved = async (payload: {
+ +
+
{{ t.taskListConfig.columns.renderMode }}
+
+ + +
+
{{ t.taskListConfig.columns.title }}
- - - -