From 281c2d9c5ba9822f67ecf6b5f2cb4fc54d8c645b Mon Sep 17 00:00:00 2001 From: "LINING-PC\\lining" Date: Fri, 12 Sep 2025 16:41:32 +0800 Subject: [PATCH] v1.3.0 - add Annual/Quarter/Hourly timeline views --- CHANGELOG.md | 20 + README-EN.md | 258 +++- README.md | 268 +++- demo/App.vue | 27 +- demo/data.json | 273 ++++ demo/version-history.json | 18 + package.json | 4 +- packageDemo/App.vue | 27 +- packageDemo/data.json | 273 ++++ packageDemo/version-history.json | 18 + src/components/DatePicker.vue | 739 +++++++++- src/components/GanttChart.vue | 22 +- src/components/GanttToolbar.vue | 71 +- src/components/MilestonePoint.vue | 261 +++- src/components/MultiSelectPredecessor.vue | 4 +- src/components/TaskBar.vue | 446 ++++-- src/components/TaskContextMenu.vue | 6 +- src/components/TaskDrawer.vue | 97 +- src/components/Timeline.vue | 1637 +++++++++++++++++++-- src/composables/useI18n.ts | 35 +- src/models/GanttTypes.ts | 0 src/models/configs/ToolbarConfig.ts | 1 + src/models/types/TimelineCompat.ts | 20 + src/models/types/TimelineDataTypes.ts | 131 ++ src/models/types/TimelineScale.ts | 29 +- src/utils/predecessorUtils.ts | 12 + tsconfig.build.json | 10 + 27 files changed, 4253 insertions(+), 454 deletions(-) delete mode 100644 src/models/GanttTypes.ts create mode 100644 src/models/types/TimelineCompat.ts create mode 100644 src/models/types/TimelineDataTypes.ts create mode 100644 tsconfig.build.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e954a2..740fd94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,26 @@ 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.3.0] - 2025-09-12 + +### Added +- 增加年度视图 +- 增加季度视图 +- 增加小时视图 +- Add annual timeline view +- Add a quarterly timeline view +- Add hourly timeline view + +### Changed +- 升级TaskDrawer中DatePicker组件,接受小时的设定 +- 升级TaskDrawer中预计时间和实际时间的控件,接受小数后两位的录入 +- Upgrade the DatePicker component in TaskDrawer to accept the setting of hours +- Upgrade the control for estimated and actual time in TaskDrawer to accept entries with two decimal places + +### Fixed +- SonarQube代码质量检查问题修改 +- Modification of SonarQube code quality inspection issues + ## [1.2.1] - 2025-07-22 ### Fixed diff --git a/README-EN.md b/README-EN.md index 6112007..37b05e3 100644 --- a/README-EN.md +++ b/README-EN.md @@ -59,26 +59,71 @@ pnpm add jordium-gantt-vue3 ``` jordium-gantt-vue3/ -├── src/ # Source code directory -│ ├── components/ # Core components -│ │ ├── GanttChart.vue # Main entry component -│ │ ├── TaskList.vue # Task list -│ │ ├── Timeline.vue # Timeline -│ │ ├── TaskBar.vue # Task bar -│ │ ├── MilestonePoint.vue # Milestone -│ │ └── ... # Other components -│ ├── models/ # Data models -│ │ ├── classes/ # Class definitions -│ │ └── configs/ # Configuration interfaces -│ ├── composables/ # Composable functions -│ ├── styles/ # Style files -│ └── index.ts # Export entry -├── demo/ # Development demo -├── dist/ # Build output -├── docs/ # Documentation -└── package.json +├── src/ # Source code directory +│ ├── components/ # Core Vue components +│ │ ├── GanttChart.vue # Main entry component +│ │ ├── TaskList.vue # Task list component +│ │ ├── Timeline.vue # Timeline component +│ │ ├── TaskBar.vue # Task bar component +│ │ ├── TaskDrawer.vue # Task edit drawer +│ │ ├── TaskContextMenu.vue # Task context menu +│ │ ├── GanttToolbar.vue # Toolbar component +│ │ ├── MilestonePoint.vue # Milestone point +│ │ ├── MilestoneDialog.vue # Milestone dialog +│ │ ├── DatePicker.vue # Date picker +│ │ └── ... # Other components +│ ├── models/ # Data models and configurations +│ │ ├── classes/ # Class definitions +│ │ │ ├── Task.ts # Task model +│ │ │ ├── Milestone.ts # Milestone model +│ │ │ └── Language.ts # Language configuration +│ │ ├── configs/ # Configuration interfaces +│ │ │ ├── TimelineConfig.ts # Timeline configuration +│ │ │ └── ToolbarConfig.ts # Toolbar configuration +│ │ └── types/ # Type definitions +│ │ └── TimelineScale.ts # Timeline scale types +│ ├── composables/ # Vue composable functions +│ │ ├── useI18n.ts # Internationalization utilities +│ │ └── useMessage.ts # Message utilities +│ ├── styles/ # Style files +│ │ ├── app.css # Main styles +│ │ └── theme-variables.css # Theme variables +│ ├── utils/ # Utility functions +│ │ └── predecessorUtils.ts # Predecessor utilities +│ └── index.ts # Export entry +├── demo/ # Development demo & interactive showcase +│ ├── App.vue # Demo application main component +│ ├── data.json # Demo data (includes clinical trial examples) +│ ├── main.ts # Demo application entry +│ └── ... # Other demo files +├── packageDemo/ # npm package integration demo +├── dist/ # Build output directory +├── docs/ # Documentation +├── design/ # Design resources and screenshots +│ └── screenshots/ # Theme screenshots +├── public/ # Public static resources +│ └── assets/ # Static asset files +├── README.md # Chinese documentation +├── README-EN.md # English documentation +├── package.json # Project configuration +├── vite.config.ts # Vite development configuration +├── vite.config.lib.ts # Vite library build configuration +├── tsconfig.json # TypeScript configuration +└── ... # Other configuration files and metadata ``` +### Directory Description + +- **`src/components/`**: Core Vue components containing all Gantt chart functionality +- **`src/models/`**: Data models, type definitions and configuration interfaces +- **`src/composables/`**: Vue 3 composable functions providing reusable logic +- **`src/styles/`**: Style files including theme system and CSS variables +- **`src/utils/`**: Utility functions for business logic and data transformation +- **`demo/`**: Local development and feature demonstration with complete interactive pages and clinical trial sample data +- **`packageDemo/`**: Simulates npm package integration in external projects +- **`dist/`**: Build output directory for npm publishing or static sites +- **`docs/`**: Project documentation including deployment guides and API references + ## 🔧 API Reference ### GanttChart Properties @@ -92,8 +137,9 @@ jordium-gantt-vue3/ | `showToolbar` | `boolean` | `true` | Show toolbar | | `toolbarConfig` | `ToolbarConfig` | `{}` | Toolbar configuration | | `localeMessages` | `Partial` | - | Custom locale messages | +| `workingHours` | `WorkingHours` | - | Working hours configuration | | `onTaskDoubleClick` | `(task: Task) => void` | - | Task double-click event callback | -| `onTaskDelete` | `(task: Task) => void` | - | Task delete event callback | +| `onTaskDelete` | `(task: Task, deleteChildren?: boolean) => void` | - | Task delete event callback | | `onTaskUpdate` | `(task: Task) => void` | - | Task update event callback | | `onTaskAdd` | `(task: Task) => void` | - | Task add event callback | | `onMilestoneSave` | `(milestone: Task) => void` | - | Milestone save event callback | @@ -184,16 +230,16 @@ function onTaskUpdated(e) { **Task Type** ```typescript export interface Task { - id: number // Unique task ID - name: string // Task name - predecessor?: number[] // Predecessor task ID array - assignee?: string // Assignee - startDate?: string // Start date (ISO string) - endDate?: string // End date (ISO string) - progress?: number // Progress percentage 0-100 - estimatedHours?: number // Estimated hours - actualHours?: number // Actual hours - parentId?: number // Parent task ID + id: number // Unique task ID + name: string // Task name + predecessor?: number[] // Predecessor task ID array + assignee?: string // Assignee + startDate?: string // Start date (ISO string) + endDate?: string // End date (ISO string) + progress?: number // Progress percentage 0-100 + estimatedHours?: number // Estimated hours (supports decimal, up to 2 decimal places) + actualHours?: number // Actual hours (supports decimal, up to 2 decimal places) + parentId?: number // Parent task ID children?: Task[] // Subtask array collapsed?: boolean // Collapsed state isParent?: boolean // Is parent task @@ -253,6 +299,86 @@ interface ToolbarConfig { } ``` +**WorkingHours Configuration** +```typescript +interface WorkingHours { + morning?: { start: number; end: number } // Morning work hours, e.g. { start: 8, end: 11 } + afternoon?: { start: number; end: number } // Afternoon work hours, e.g. { start: 13, end: 17 } +} +``` + +**TimelineScale Types** +```typescript +// Timeline display scale types +type TimelineScale = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year' + +// Timeline scale constants +export const TimelineScale = { + HOUR: 'hour', // Hour view - each column displays one hour + DAY: 'day', // Day view - each column displays one day + WEEK: 'week', // Week view - each column displays one week + MONTH: 'month', // Month view - each column displays one month + QUARTER: 'quarter', // Quarter view - each column displays one quarter + YEAR: 'year', // Year view - each column displays one year +} + +// Timeline scale configuration +interface TimelineScaleConfig { + scale: TimelineScale // Scale type + cellWidth: number // Width of each time unit (px) + headerLevels: number // Number of header levels + formatters: { + primary: string // Primary time label format + secondary?: string // Secondary time label format + } +} +``` + +### 🕐 Timeline Scale Features + +The component supports multiple timeline scale displays. Users can switch timeline granularity through the Day/Week/Month button group in the toolbar or programmatically: + +#### Built-in Scale Configurations + +| Scale Type | Cell Width | Primary Format | Secondary Format | Use Case | +|------------|------------|----------------|------------------|----------| +| `hour` | 40px | yyyy/MM/dd | HH | Short-term projects with hourly precision, such as drug clinical trials | +| `day` | 30px | yyyy/MM | dd | Standard view for daily project management | +| `week` | 120px | yyyy/MM | W | Weekly planning view for medium-term projects | +| `month` | 180px | yyyy | MM | Monthly view for long-term projects | +| `quarter` | 360px | yyyy | Q | Quarterly view for strategic planning | +| `year` | 360px | yyyy | First Half\|Second Half | Annual view for very long-term projects | + +#### Usage Example + +```vue + + + +``` + #### Composable Functions (src/composables) **useI18n Internationalization Tool** @@ -399,6 +525,80 @@ const customLocaleMessages = { addTask: 'Custom Add Task' } +// Handle toolbar events +const handleLanguageChange = (lang) => { + console.log('Language switched to:', lang) +} + +const handleThemeChange = (isDark) => { + console.log('Theme switched to:', isDark ? 'dark' : 'light') +} + +// Listen to timeline scale changes +const handleTimeScaleChange = (scale) => { + console.log('Timeline scale changed to:', scale) + // Adjust display logic based on scale + if (scale === 'day') { + // Special handling for day view + } else if (scale === 'week') { + // Special handling for week view + } +} + + + +``` + +### 🔧 Working Hours Configuration + +The component supports setting working hours, affecting task duration calculations and progress display: + +```vue + + + +``` + +### 📊 High-Precision Work Hours Management + +The component supports work hour recording precise to 2 decimal places, suitable for projects requiring precise billing: + +```vue + +``` + // Handle toolbar events const handleLanguageChange = (lang) => { console.log('Language changed to:', lang) diff --git a/README.md b/README.md index eb0c1d4..438abe8 100644 --- a/README.md +++ b/README.md @@ -60,28 +60,70 @@ pnpm add jordium-gantt-vue3 ``` jordium-gantt-vue3/ -├── src/ # 组件源码与核心逻辑 -│ ├── components/ # 主要 Vue 组件 -│ ├── models/ # 数据类型与配置 -│ ├── composables/ # 组合式函数 -│ ├── styles/ # 样式文件 -│ └── index.ts # 入口导出 -├── demo/ # 组件开发与交互演示(本地开发/预览用) -├── packageDemo/ # npm 包集成演示(模拟外部项目集成效果) -├── dist/ # 构建产物(发布/静态站点/打包输出) -├── docs/ # 相关文档(如部署、API 说明等) -├── design/ # 设计资源与截图 -├── public/ # 公共静态资源 -├── README.md # 中文说明文档 -├── README-EN.md # 英文说明文档 -└── ... # 其他配置、脚本与元数据 +├── src/ # 组件源码与核心逻辑 +│ ├── components/ # 主要 Vue 组件 +│ │ ├── GanttChart.vue # 主入口组件 +│ │ ├── TaskList.vue # 任务列表 +│ │ ├── Timeline.vue # 时间轴组件 +│ │ ├── TaskBar.vue # 任务条 +│ │ ├── TaskDrawer.vue # 任务编辑抽屉 +│ │ ├── TaskContextMenu.vue # 任务右键菜单 +│ │ ├── GanttToolbar.vue # 工具栏 +│ │ ├── MilestonePoint.vue # 里程碑点 +│ │ ├── MilestoneDialog.vue # 里程碑对话框 +│ │ ├── DatePicker.vue # 日期选择器 +│ │ └── ... # 其他组件 +│ ├── models/ # 数据模型与配置 +│ │ ├── classes/ # 类定义 +│ │ │ ├── Task.ts # 任务模型 +│ │ │ ├── Milestone.ts # 里程碑模型 +│ │ │ └── Language.ts # 语言配置 +│ │ ├── configs/ # 配置接口 +│ │ │ ├── TimelineConfig.ts # 时间轴配置 +│ │ │ └── ToolbarConfig.ts # 工具栏配置 +│ │ └── types/ # 类型定义 +│ │ └── TimelineScale.ts # 时间刻度类型 +│ ├── composables/ # 组合式函数 +│ │ ├── useI18n.ts # 国际化工具 +│ │ └── useMessage.ts # 消息提示工具 +│ ├── styles/ # 样式文件 +│ │ ├── app.css # 主样式 +│ │ └── theme-variables.css # 主题变量 +│ ├── utils/ # 工具函数 +│ │ └── predecessorUtils.ts # 前置依赖工具 +│ └── index.ts # 入口导出 +├── demo/ # 组件开发与交互演示(本地开发/预览用) +│ ├── App.vue # 演示应用主组件 +│ ├── data.json # 演示数据(包含药物临床试验案例) +│ ├── main.ts # 演示应用入口 +│ └── ... # 其他演示文件 +├── packageDemo/ # npm 包集成演示(模拟外部项目集成效果) +├── dist/ # 构建产物(发布/静态站点/打包输出) +├── docs/ # 相关文档(如部署、API 说明等) +├── design/ # 设计资源与截图 +│ └── screenshots/ # 主题截图 +├── public/ # 公共静态资源 +│ └── assets/ # 静态资源文件 +├── README.md # 中文说明文档 +├── README-EN.md # 英文说明文档 +├── package.json # 项目配置 +├── vite.config.ts # Vite开发配置 +├── vite.config.lib.ts # Vite库构建配置 +├── tsconfig.json # TypeScript配置 +└── ... # 其他配置、脚本与元数据 ``` -- `demo/`:用于本地开发和功能演示,包含完整的交互页面。 -- `packageDemo/`:用于模拟 npm 包在外部项目中的集成与使用场景。 -- `dist/`:构建输出目录,包含发布到 npm 或静态站点的产物。 -- `docs/`:项目相关文档,如部署说明、API 参考等。 -- 其余目录请参考注释。 +### 目录说明 + +- **`src/components/`**:核心Vue组件,包含甘特图的所有功能组件 +- **`src/models/`**:数据模型、类型定义和配置接口 +- **`src/composables/`**:Vue 3组合式函数,提供可复用的逻辑 +- **`src/styles/`**:样式文件,包含主题系统和CSS变量 +- **`src/utils/`**:工具函数,处理业务逻辑和数据转换 +- **`demo/`**:本地开发和功能演示,包含完整的交互页面和药物临床试验样例数据 +- **`packageDemo/`**:模拟npm包在外部项目中的集成与使用场景 +- **`dist/`**:构建输出目录,包含发布到npm或静态站点的产物 +- **`docs/`**:项目文档,包括部署说明、API参考等 ## 🔧 API 参考 @@ -96,8 +138,22 @@ jordium-gantt-vue3/ | `showToolbar` | `boolean` | `true` | 是否显示工具栏 | | `toolbarConfig` | `ToolbarConfig` | `{}` | 工具栏配置 | | `localeMessages` | `Partial` | - | 自定义多语言配置 | +| `workingHours` | `WorkingHours` | - | 工作时间配置 | | `onTaskDoubleClick` | `(task: Task) => void` | - | 任务双击事件回调 | -| `onTaskDelete` | `(task: Task) => void` | - | 任务删除事件回调 | +| `onTaskDelete` | `(task: Task, deleteChildren?: boolean) => void` | - | 任务删除事件回调 | +| `onTaskUpdate` | `(task: Task) => void` | - | 任务更新事件回调 | +| `onTaskAdd` | `(task: Task) => void` | - | 任务添加事件回调 | +| `onMilestoneSave` | `(milestone: Task) => void` | - | 里程碑保存事件回调 | +| `onMilestoneDelete` | `(milestoneId: number) => void` | - | 里程碑删除事件回调 | +| `onMilestoneIconChange` | `(milestoneId: number, icon: string) => void` | - | 里程碑图标变更事件回调 | +| `onAddTask` | `() => void` | - | 新增任务工具栏事件回调 | +| `onAddMilestone` | `() => void` | - | 新增里程碑工具栏事件回调 | +| `onTodayLocate` | `() => void` | - | 定位今天工具栏事件回调 | +| `onExportCsv` | `() => boolean \| void` | - | 导出CSV工具栏事件回调 | +| `onExportPdf` | `() => void` | - | 导出PDF工具栏事件回调 | +| `onLanguageChange` | `(lang: 'zh-CN' \| 'en-US') => void` | - | 语言切换工具栏事件回调 | +| `onThemeChange` | `(isDark: boolean) => void` | - | 主题切换工具栏事件回调 | +| `onFullscreenChange` | `(isFullscreen: boolean) => void` | - | 全屏切换工具栏事件回调 | | `onTaskUpdate` | `(task: Task) => void` | - | 任务更新事件回调 | | `onTaskAdd` | `(task: Task) => void` | - | 任务添加事件回调 | | `onMilestoneSave` | `(milestone: Task) => void` | - | 里程碑保存事件回调 | @@ -188,16 +244,16 @@ function onTaskUpdated(e) { **Task 任务类型** ```typescript export interface Task { - id: number // 任务唯一ID - name: string // 任务名称 - predecessor?: number[] // 前置任务ID数组 - assignee?: string // 负责人 - startDate?: string // 开始日期(ISO字符串) - endDate?: string // 结束日期(ISO字符串) - progress?: number // 进度百分比 0-100 - estimatedHours?: number // 预估工时 - actualHours?: number // 实际工时 - parentId?: number // 上级任务ID + id: number // 任务唯一ID + name: string // 任务名称 + predecessor?: number[] // 前置任务ID数组 + assignee?: string // 负责人 + startDate?: string // 开始日期(ISO字符串) + endDate?: string // 结束日期(ISO字符串) + progress?: number // 进度百分比 0-100 + estimatedHours?: number // 预估工时(支持小数,最多2位) + actualHours?: number // 实际工时(支持小数,最多2位) + parentId?: number // 上级任务ID children?: Task[] // 子任务数组 collapsed?: boolean // 是否折叠 isParent?: boolean // 是否为父任务 @@ -257,6 +313,86 @@ interface ToolbarConfig { } ``` +**WorkingHours 工作时间配置** +```typescript +interface WorkingHours { + morning?: { start: number; end: number } // 上午工作时间,如 { start: 8, end: 11 } + afternoon?: { start: number; end: number } // 下午工作时间,如 { start: 13, end: 17 } +} +``` + +**TimelineScale 时间刻度类型** +```typescript +// 时间轴显示刻度类型 +type TimelineScale = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year' + +// 时间刻度常量 +export const TimelineScale = { + HOUR: 'hour', // 小时视图 - 每列显示一小时 + DAY: 'day', // 日视图 - 每列显示一天 + WEEK: 'week', // 周视图 - 每列显示一周 + MONTH: 'month', // 月视图 - 每列显示一个月 + QUARTER: 'quarter', // 季度视图 - 每列显示一个季度 + YEAR: 'year', // 年视图 - 每列显示一年 +} + +// 时间刻度配置 +interface TimelineScaleConfig { + scale: TimelineScale // 刻度类型 + cellWidth: number // 每个时间单元的宽度(px) + headerLevels: number // 表头层级数 + formatters: { + primary: string // 主要时间标签格式 + secondary?: string // 次要时间标签格式 + } +} +``` + +### 🕐 时间刻度功能说明 + +组件支持多种时间刻度显示,用户可以通过工具栏的日/周/月按钮组或者编程方式切换时间轴的显示粒度: + +#### 内置刻度配置 + +| 刻度类型 | 单元宽度 | 主标签格式 | 副标签格式 | 适用场景 | +|----------|----------|------------|------------|----------| +| `hour` | 40px | yyyy/MM/dd | HH | 精确到小时的项目, 例如药物临床试验 | +| `day` | 30px | yyyy年MM月 | dd | 日常项目管理的标准视图 | +| `week` | 120px | yyyy年MM月 | W | 中期项目的周计划视图 | +| `month` | 180px | yyyy | MM | 长期项目的月度视图 | +| `quarter` | 360px | yyyy | Q | 战略规划的季度视图 | +| `year` | 360px | yyyy | 上半年\|下半年 | 超长期项目年度视图 | + +#### 使用示例 + +```vue + + + +``` + #### 组合式函数 (src/composables) **useI18n 国际化工具** @@ -386,15 +522,15 @@ import { GanttChart } from 'jordium-gantt-vue3' // 工具栏配置 const toolbarConfig = { - showLanguage: true, - showTheme: true, - showAddTask: true, - showAddMilestone: true, - showTodayLocate: true, - showExportCsv: true, - showExportPdf: true, - showFullscreen: true, - showTimeScale: true // 控制日|周|月时间刻度按钮组的可见性 + showLanguage: true, // 语言切换 + showTheme: true, // 主题切换 + showAddTask: true, // 新增任务 + showAddMilestone: true, // 新增里程碑 + showTodayLocate: true, // 定位今天 + showExportCsv: true, // 导出CSV + showExportPdf: true, // 导出PDF + showFullscreen: true, // 全屏模式 + showTimeScale: true // 时间刻度切换(日|周|月按钮组) } // 自定义多语言配置 @@ -411,6 +547,17 @@ const handleLanguageChange = (lang) => { const handleThemeChange = (isDark) => { console.log('主题切换到:', isDark ? '暗色' : '亮色') } + +// 监听时间刻度变化 +const handleTimeScaleChange = (scale) => { + console.log('时间刻度切换至:', scale) + // 根据刻度调整显示逻辑 + if (scale === 'day') { + // 日视图下的特殊处理 + } else if (scale === 'week') { + // 周视图下的特殊处理 + } +} ``` +### 🔧 工作时间配置 + +组件支持设置工作时间,影响任务时长计算和进度显示: + +```vue + + + +``` + +### 📊 高精度工时管理 + +组件支持精确到小数点后2位的工时记录,适合需要精确计费的项目: + +```vue + +``` + ## 🤝 贡献与合作 ### 参与贡献 diff --git a/demo/App.vue b/demo/App.vue index 57d2326..3fa9ee1 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -37,6 +37,14 @@ const toolbarConfig = { showTheme: true, showFullscreen: true, showTimeScale: true, // 控制日|周|月时间刻度按钮组的可见性 + timeScaleDimensions: ['hour', 'day', 'week', 'month', 'quarter', 'year'], // 设置时间刻度按钮的展示维度,包含所有时间维度 +} + +// 工作时间配置示例 +const workingHoursConfig = { + morning: { start: 8, end: 11 }, // 上午8:00-11:59为工作时间 + afternoon: { start: 13, end: 17 }, // 下午13:00-17:00为工作时间 + // 其他时间(12:00-12:59, 18:00-07:59)为休息时间,显示为灰色背景 } // 自定义CSV导出处理器(可选) @@ -118,14 +126,14 @@ const handleMilestoneDelete = async (milestoneId: number) => { window.dispatchEvent( new CustomEvent('milestone-deleted', { detail: { milestoneId }, - }) + }), ) // 触发强制更新事件,确保Timeline重新渲染 window.dispatchEvent( new CustomEvent('milestone-data-changed', { detail: { milestones: milestones.value }, - }) + }), ) } @@ -219,7 +227,7 @@ const handleTaskUpdate = (updatedTask: Task) => { showMessage( formatTranslation('newParentTaskNotFound', { parentId: taskToAdd.parentId }), 'warning', - { closable: true } + { closable: true }, ) tasks.value.push(taskToAdd) } @@ -267,7 +275,7 @@ const handleTaskAdd = (newTask: Task) => { const maxId = Math.max( ...tasks.value.map(t => t.id || 0), ...milestones.value.map(m => m.id || 0), - 0 + 0, ) newTask.id = maxId + 1 } @@ -362,7 +370,7 @@ const handleStoryDeleteWithChildren = (storyToDelete: Task) => { 'success', { closable: false, - } + }, ) return true } @@ -424,7 +432,7 @@ const handleStoryDeleteOnly = (storyToDelete: Task) => { 'success', { closable: false, - } + }, ) return true } @@ -498,7 +506,7 @@ function handleTaskbarDragOrResizeEnd(newTask) { `开始: ${oldTask.startDate} → ${newTask.startDate}\n` + `结束: ${oldTask.endDate} → ${newTask.endDate}`, 'info', - { closable: true } + { closable: true }, ) } function handleMilestoneDragEnd(newMilestone) { @@ -508,7 +516,7 @@ function handleMilestoneDragEnd(newMilestone) { `里程碑【${newMilestone.name}】\n` + `开始: ${oldMilestone.endDate} → ${newMilestone.startDate}`, 'info', - { closable: true } + { closable: true }, ) } @@ -575,7 +583,7 @@ function onTimerStarted(task: Task) { showMessage( `Demo 任务【${task.name}】\n开始计时:${new Date(task.timerStartTime).toLocaleString()}\n计时说明:${task.timerStartDesc ? task.timerStartDesc : ''}`, 'info', - { closable: true } + { closable: true }, ) } function onTimerStopped(task: Task) { @@ -628,6 +636,7 @@ function onTimerStopped(task: Task) { :tasks="tasks" :milestones="milestones" :toolbar-config="toolbarConfig" + :working-hours="workingHoursConfig" :on-add-task="handleAddTask" :on-add-milestone="handleAddMilestone" :on-export-csv="handleCustomCsvExport" diff --git a/demo/data.json b/demo/data.json index 376d687..67f2f9f 100644 --- a/demo/data.json +++ b/demo/data.json @@ -1,5 +1,248 @@ { "tasks": [ + { + "id": 1000, + "name": "新药ADX-2024临床试验项目", + "assignee": "首席研究员 Dr. Chen", + "startDate": "2025-01-01", + "endDate": "2027-12-31", + "progress": 15, + "estimatedHours": 26280.5, + "actualHours": 3942.75, + "type": "story", + "description": "ADX-2024新药完整临床试验计划,从I期到III期临床试验", + "children": [ + { + "id": 1100, + "name": "I期临床试验", + "assignee": "I期试验主任 Dr. Wang", + "startDate": "2025-01-01", + "endDate": "2025-08-31", + "progress": 65, + "estimatedHours": 5256, + "actualHours": 3417, + "type": "story", + "parentId": 1000, + "description": "评估ADX-2024在健康志愿者和患者中的安全性、耐受性和药代动力学特征", + "children": [ + { + "id": 1101, + "name": "试验方案设计与伦理审查", + "assignee": "方案设计师 李明", + "startDate": "2025-01-01", + "endDate": "2025-02-28", + "progress": 100, + "estimatedHours": 464, + "actualHours": 480, + "type": "task", + "parentId": 1100, + "description": "完成I期试验方案设计、伦理委员会审批及监管部门申报" + }, + { + "id": 1102, + "name": "受试者招募与筛选", + "assignee": "招募专员 张丽", + "startDate": "2025-03-01", + "endDate": "2025-04-30", + "progress": 90, + "estimatedHours": 1392.5, + "actualHours": 1250.25, + "type": "task", + "predecessor": [1101], + "parentId": 1100, + "description": "招募24名健康志愿者,完成医学筛选和入组评估" + }, + { + "id": 1103, + "name": "药物给药与安全性监测", + "assignee": "临床医生 Dr. Liu", + "startDate": "2025-05-01", + "endDate": "2025-08-31", + "progress": 40, + "estimatedHours": 3400, + "actualHours": 1687, + "type": "task", + "predecessor": [1102], + "parentId": 1100, + "description": "按照剂量递增方案给药,密切监测不良反应和药代动力学参数" + } + ], + "collapsed": false + }, + { + "id": 1200, + "name": "II期临床试验", + "assignee": "II期试验主任 Dr. Zhang", + "startDate": "2025-09-01", + "endDate": "2026-08-31", + "progress": 5, + "estimatedHours": 8760.75, + "actualHours": 438.25, + "type": "story", + "parentId": 1000, + "description": "在目标患者群体中评估ADX-2024的初步疗效和进一步的安全性", + "children": [ + { + "id": 1201, + "name": "多中心试验启动", + "assignee": "项目经理 王芳", + "startDate": "2025-09-01", + "endDate": "2025-11-30", + "progress": 25, + "estimatedHours": 2160, + "actualHours": 324, + "type": "task", + "predecessor": [1103], + "parentId": 1200, + "description": "启动5个临床中心,完成研究者培训和质量体系建立" + }, + { + "id": 1202, + "name": "患者入组与随机化", + "assignee": "数据管理员 陈静", + "startDate": "2025-12-01", + "endDate": "2026-03-31", + "progress": 0, + "estimatedHours": 2880, + "actualHours": 0, + "type": "task", + "predecessor": [1201], + "parentId": 1200, + "description": "计划入组120名患者,采用双盲随机对照设计" + }, + { + "id": 1203, + "name": "疗效评估与数据收集", + "assignee": "统计师 赵磊", + "startDate": "2026-01-01", + "endDate": "2026-08-31", + "progress": 0, + "estimatedHours": 3720, + "actualHours": 0, + "type": "task", + "predecessor": [1202], + "parentId": 1200, + "description": "定期评估患者疗效指标,收集安全性数据,进行中期分析" + } + ], + "collapsed": false + }, + { + "id": 1300, + "name": "III期临床试验", + "assignee": "III期试验主任 Dr. Li", + "startDate": "2026-09-01", + "endDate": "2027-12-31", + "progress": 0, + "estimatedHours": 12264, + "actualHours": 0, + "type": "story", + "parentId": 1000, + "description": "大规模多中心随机对照试验,确认ADX-2024的疗效和安全性", + "children": [ + { + "id": 1301, + "name": "国际多中心试验准备", + "assignee": "国际事务专员 刘倩", + "startDate": "2026-09-01", + "endDate": "2026-12-31", + "progress": 0, + "estimatedHours": 2928, + "actualHours": 0, + "type": "task", + "predecessor": [1203], + "parentId": 1300, + "description": "启动15个国际临床中心,获得各国监管审批" + }, + { + "id": 1302, + "name": "大规模患者招募", + "assignee": "多中心协调员 孙伟", + "startDate": "2027-01-01", + "endDate": "2027-06-30", + "progress": 0, + "estimatedHours": 4380, + "actualHours": 0, + "type": "task", + "predecessor": [1301], + "parentId": 1300, + "description": "计划入组500名患者,严格按照纳排标准执行" + }, + { + "id": 1303, + "name": "最终疗效分析与报告", + "assignee": "首席统计师 马强", + "startDate": "2027-03-01", + "endDate": "2027-12-31", + "progress": 0, + "estimatedHours": 4956, + "actualHours": 0, + "type": "task", + "predecessor": [1302], + "parentId": 1300, + "description": "完成最终疗效分析,撰写临床研究报告,准备新药上市申请" + } + ], + "collapsed": false + } + ], + "collapsed": false + }, + { + "id": 1001, + "name": "上午会议", + "assignee": "测试用户", + "startDate": "2025-09-10 09:00", + "endDate": "2025-09-10 10:30", + "progress": 50, + "estimatedHours": 1.5, + "actualHours": 0.75, + "type": "task" + }, + { + "id": 1002, + "name": "午后开发", + "assignee": "开发者", + "startDate": "2025-09-10 14:00", + "endDate": "2025-09-10 16:15", + "progress": 30, + "estimatedHours": 2.25, + "actualHours": 1.33, + "type": "task" + }, + { + "id": 1003, + "name": "测试任务", + "assignee": "测试员", + "startDate": "2025-09-10 16:30", + "endDate": "2025-09-10 17:45", + "progress": 0, + "estimatedHours": 1.25, + "actualHours": 0, + "type": "task" + }, + { + "id": 1004, + "name": "当日整天任务", + "assignee": "项目经理", + "startDate": "2025-09-10", + "endDate": "2025-09-10", + "progress": 20, + "estimatedHours": 8.0, + "actualHours": 1.5, + "type": "task" + }, + { + "id": 1005, + "name": "12点瞬间任务", + "assignee": "测试员", + "startDate": "2025-09-10 12:00", + "endDate": "2025-09-10 12:00", + "progress": 100, + "estimatedHours": 0, + "actualHours": 0, + "type": "task" + }, { "id": 1, "name": "项目启动", @@ -162,6 +405,36 @@ } ], "milestones": [ + { + "id": 1150, + "name": "I期临床试验完成", + "assignee": "I期试验主任 Dr. Wang", + "startDate": "2025-08-31", + "endDate": "2025-08-31", + "type": "milestone", + "icon": "shield-check", + "description": "完成I期临床试验,确认ADX-2024在人体的安全性和耐受性,为II期试验奠定基础。" + }, + { + "id": 1250, + "name": "II期临床中期分析", + "assignee": "统计师 赵磊", + "startDate": "2026-04-30", + "endDate": "2026-04-30", + "type": "milestone", + "icon": "bar-chart", + "description": "完成II期临床试验中期疗效分析,评估是否继续进行III期试验。" + }, + { + "id": 1350, + "name": "新药上市申请提交", + "assignee": "首席研究员 Dr. Chen", + "startDate": "2027-12-31", + "endDate": "2027-12-31", + "type": "milestone", + "icon": "trophy", + "description": "完成III期临床试验最终分析,向监管部门提交新药上市申请(NDA)。" + }, { "id": 6, "name": "技术选型完成", diff --git a/demo/version-history.json b/demo/version-history.json index bfe29c6..db38be4 100644 --- a/demo/version-history.json +++ b/demo/version-history.json @@ -162,5 +162,23 @@ "version": "1.2.1", "date": "2025-07-22", "notes": ["SonarQube代码质量检查问题修改"] + }, + { + "version": "1.3.0", + "date": "2025-09-12", + "notes": [ + "增加年度视图", + "Add annual timeline view", + "增加季度视图", + "Add quarterly timeline view", + "增加小时视图", + "Add hourly timeline view", + "升级TaskDrawer中DatePicker组件,接受小时的设定", + "Upgrade DatePicker component in TaskDrawer to accept hour settings", + "升级TaskDrawer中预计时间和实际时间的控件,接受小数后两位的录入", + "Upgrade the estimated time and actual time controls in TaskDrawer to accept two decimal places", + "SonarQube代码质量检查问题修改", + "SonarQube code quality inspection issue modification" + ] } ] diff --git a/package.json b/package.json index 4c2cbe7..5cef070 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jordium-gantt-vue3", - "version": "1.2.1", + "version": "1.3.0", "type": "module", "main": "dist/jordium-gantt-vue3.cjs.js", "module": "dist/jordium-gantt-vue3.es.js", @@ -48,7 +48,7 @@ "scripts": { "dev": "vite", "dev:demo": "vite", - "build": "vue-tsc -b && vite build", + "build": "vue-tsc --noEmit --skipLibCheck && vite build", "build:demo": "vue-tsc -b && vite build", "build:lib": "vite build --config vite.config.lib.ts", "preview": "vite preview", diff --git a/packageDemo/App.vue b/packageDemo/App.vue index 57d2326..3fa9ee1 100644 --- a/packageDemo/App.vue +++ b/packageDemo/App.vue @@ -37,6 +37,14 @@ const toolbarConfig = { showTheme: true, showFullscreen: true, showTimeScale: true, // 控制日|周|月时间刻度按钮组的可见性 + timeScaleDimensions: ['hour', 'day', 'week', 'month', 'quarter', 'year'], // 设置时间刻度按钮的展示维度,包含所有时间维度 +} + +// 工作时间配置示例 +const workingHoursConfig = { + morning: { start: 8, end: 11 }, // 上午8:00-11:59为工作时间 + afternoon: { start: 13, end: 17 }, // 下午13:00-17:00为工作时间 + // 其他时间(12:00-12:59, 18:00-07:59)为休息时间,显示为灰色背景 } // 自定义CSV导出处理器(可选) @@ -118,14 +126,14 @@ const handleMilestoneDelete = async (milestoneId: number) => { window.dispatchEvent( new CustomEvent('milestone-deleted', { detail: { milestoneId }, - }) + }), ) // 触发强制更新事件,确保Timeline重新渲染 window.dispatchEvent( new CustomEvent('milestone-data-changed', { detail: { milestones: milestones.value }, - }) + }), ) } @@ -219,7 +227,7 @@ const handleTaskUpdate = (updatedTask: Task) => { showMessage( formatTranslation('newParentTaskNotFound', { parentId: taskToAdd.parentId }), 'warning', - { closable: true } + { closable: true }, ) tasks.value.push(taskToAdd) } @@ -267,7 +275,7 @@ const handleTaskAdd = (newTask: Task) => { const maxId = Math.max( ...tasks.value.map(t => t.id || 0), ...milestones.value.map(m => m.id || 0), - 0 + 0, ) newTask.id = maxId + 1 } @@ -362,7 +370,7 @@ const handleStoryDeleteWithChildren = (storyToDelete: Task) => { 'success', { closable: false, - } + }, ) return true } @@ -424,7 +432,7 @@ const handleStoryDeleteOnly = (storyToDelete: Task) => { 'success', { closable: false, - } + }, ) return true } @@ -498,7 +506,7 @@ function handleTaskbarDragOrResizeEnd(newTask) { `开始: ${oldTask.startDate} → ${newTask.startDate}\n` + `结束: ${oldTask.endDate} → ${newTask.endDate}`, 'info', - { closable: true } + { closable: true }, ) } function handleMilestoneDragEnd(newMilestone) { @@ -508,7 +516,7 @@ function handleMilestoneDragEnd(newMilestone) { `里程碑【${newMilestone.name}】\n` + `开始: ${oldMilestone.endDate} → ${newMilestone.startDate}`, 'info', - { closable: true } + { closable: true }, ) } @@ -575,7 +583,7 @@ function onTimerStarted(task: Task) { showMessage( `Demo 任务【${task.name}】\n开始计时:${new Date(task.timerStartTime).toLocaleString()}\n计时说明:${task.timerStartDesc ? task.timerStartDesc : ''}`, 'info', - { closable: true } + { closable: true }, ) } function onTimerStopped(task: Task) { @@ -628,6 +636,7 @@ function onTimerStopped(task: Task) { :tasks="tasks" :milestones="milestones" :toolbar-config="toolbarConfig" + :working-hours="workingHoursConfig" :on-add-task="handleAddTask" :on-add-milestone="handleAddMilestone" :on-export-csv="handleCustomCsvExport" diff --git a/packageDemo/data.json b/packageDemo/data.json index 376d687..67f2f9f 100644 --- a/packageDemo/data.json +++ b/packageDemo/data.json @@ -1,5 +1,248 @@ { "tasks": [ + { + "id": 1000, + "name": "新药ADX-2024临床试验项目", + "assignee": "首席研究员 Dr. Chen", + "startDate": "2025-01-01", + "endDate": "2027-12-31", + "progress": 15, + "estimatedHours": 26280.5, + "actualHours": 3942.75, + "type": "story", + "description": "ADX-2024新药完整临床试验计划,从I期到III期临床试验", + "children": [ + { + "id": 1100, + "name": "I期临床试验", + "assignee": "I期试验主任 Dr. Wang", + "startDate": "2025-01-01", + "endDate": "2025-08-31", + "progress": 65, + "estimatedHours": 5256, + "actualHours": 3417, + "type": "story", + "parentId": 1000, + "description": "评估ADX-2024在健康志愿者和患者中的安全性、耐受性和药代动力学特征", + "children": [ + { + "id": 1101, + "name": "试验方案设计与伦理审查", + "assignee": "方案设计师 李明", + "startDate": "2025-01-01", + "endDate": "2025-02-28", + "progress": 100, + "estimatedHours": 464, + "actualHours": 480, + "type": "task", + "parentId": 1100, + "description": "完成I期试验方案设计、伦理委员会审批及监管部门申报" + }, + { + "id": 1102, + "name": "受试者招募与筛选", + "assignee": "招募专员 张丽", + "startDate": "2025-03-01", + "endDate": "2025-04-30", + "progress": 90, + "estimatedHours": 1392.5, + "actualHours": 1250.25, + "type": "task", + "predecessor": [1101], + "parentId": 1100, + "description": "招募24名健康志愿者,完成医学筛选和入组评估" + }, + { + "id": 1103, + "name": "药物给药与安全性监测", + "assignee": "临床医生 Dr. Liu", + "startDate": "2025-05-01", + "endDate": "2025-08-31", + "progress": 40, + "estimatedHours": 3400, + "actualHours": 1687, + "type": "task", + "predecessor": [1102], + "parentId": 1100, + "description": "按照剂量递增方案给药,密切监测不良反应和药代动力学参数" + } + ], + "collapsed": false + }, + { + "id": 1200, + "name": "II期临床试验", + "assignee": "II期试验主任 Dr. Zhang", + "startDate": "2025-09-01", + "endDate": "2026-08-31", + "progress": 5, + "estimatedHours": 8760.75, + "actualHours": 438.25, + "type": "story", + "parentId": 1000, + "description": "在目标患者群体中评估ADX-2024的初步疗效和进一步的安全性", + "children": [ + { + "id": 1201, + "name": "多中心试验启动", + "assignee": "项目经理 王芳", + "startDate": "2025-09-01", + "endDate": "2025-11-30", + "progress": 25, + "estimatedHours": 2160, + "actualHours": 324, + "type": "task", + "predecessor": [1103], + "parentId": 1200, + "description": "启动5个临床中心,完成研究者培训和质量体系建立" + }, + { + "id": 1202, + "name": "患者入组与随机化", + "assignee": "数据管理员 陈静", + "startDate": "2025-12-01", + "endDate": "2026-03-31", + "progress": 0, + "estimatedHours": 2880, + "actualHours": 0, + "type": "task", + "predecessor": [1201], + "parentId": 1200, + "description": "计划入组120名患者,采用双盲随机对照设计" + }, + { + "id": 1203, + "name": "疗效评估与数据收集", + "assignee": "统计师 赵磊", + "startDate": "2026-01-01", + "endDate": "2026-08-31", + "progress": 0, + "estimatedHours": 3720, + "actualHours": 0, + "type": "task", + "predecessor": [1202], + "parentId": 1200, + "description": "定期评估患者疗效指标,收集安全性数据,进行中期分析" + } + ], + "collapsed": false + }, + { + "id": 1300, + "name": "III期临床试验", + "assignee": "III期试验主任 Dr. Li", + "startDate": "2026-09-01", + "endDate": "2027-12-31", + "progress": 0, + "estimatedHours": 12264, + "actualHours": 0, + "type": "story", + "parentId": 1000, + "description": "大规模多中心随机对照试验,确认ADX-2024的疗效和安全性", + "children": [ + { + "id": 1301, + "name": "国际多中心试验准备", + "assignee": "国际事务专员 刘倩", + "startDate": "2026-09-01", + "endDate": "2026-12-31", + "progress": 0, + "estimatedHours": 2928, + "actualHours": 0, + "type": "task", + "predecessor": [1203], + "parentId": 1300, + "description": "启动15个国际临床中心,获得各国监管审批" + }, + { + "id": 1302, + "name": "大规模患者招募", + "assignee": "多中心协调员 孙伟", + "startDate": "2027-01-01", + "endDate": "2027-06-30", + "progress": 0, + "estimatedHours": 4380, + "actualHours": 0, + "type": "task", + "predecessor": [1301], + "parentId": 1300, + "description": "计划入组500名患者,严格按照纳排标准执行" + }, + { + "id": 1303, + "name": "最终疗效分析与报告", + "assignee": "首席统计师 马强", + "startDate": "2027-03-01", + "endDate": "2027-12-31", + "progress": 0, + "estimatedHours": 4956, + "actualHours": 0, + "type": "task", + "predecessor": [1302], + "parentId": 1300, + "description": "完成最终疗效分析,撰写临床研究报告,准备新药上市申请" + } + ], + "collapsed": false + } + ], + "collapsed": false + }, + { + "id": 1001, + "name": "上午会议", + "assignee": "测试用户", + "startDate": "2025-09-10 09:00", + "endDate": "2025-09-10 10:30", + "progress": 50, + "estimatedHours": 1.5, + "actualHours": 0.75, + "type": "task" + }, + { + "id": 1002, + "name": "午后开发", + "assignee": "开发者", + "startDate": "2025-09-10 14:00", + "endDate": "2025-09-10 16:15", + "progress": 30, + "estimatedHours": 2.25, + "actualHours": 1.33, + "type": "task" + }, + { + "id": 1003, + "name": "测试任务", + "assignee": "测试员", + "startDate": "2025-09-10 16:30", + "endDate": "2025-09-10 17:45", + "progress": 0, + "estimatedHours": 1.25, + "actualHours": 0, + "type": "task" + }, + { + "id": 1004, + "name": "当日整天任务", + "assignee": "项目经理", + "startDate": "2025-09-10", + "endDate": "2025-09-10", + "progress": 20, + "estimatedHours": 8.0, + "actualHours": 1.5, + "type": "task" + }, + { + "id": 1005, + "name": "12点瞬间任务", + "assignee": "测试员", + "startDate": "2025-09-10 12:00", + "endDate": "2025-09-10 12:00", + "progress": 100, + "estimatedHours": 0, + "actualHours": 0, + "type": "task" + }, { "id": 1, "name": "项目启动", @@ -162,6 +405,36 @@ } ], "milestones": [ + { + "id": 1150, + "name": "I期临床试验完成", + "assignee": "I期试验主任 Dr. Wang", + "startDate": "2025-08-31", + "endDate": "2025-08-31", + "type": "milestone", + "icon": "shield-check", + "description": "完成I期临床试验,确认ADX-2024在人体的安全性和耐受性,为II期试验奠定基础。" + }, + { + "id": 1250, + "name": "II期临床中期分析", + "assignee": "统计师 赵磊", + "startDate": "2026-04-30", + "endDate": "2026-04-30", + "type": "milestone", + "icon": "bar-chart", + "description": "完成II期临床试验中期疗效分析,评估是否继续进行III期试验。" + }, + { + "id": 1350, + "name": "新药上市申请提交", + "assignee": "首席研究员 Dr. Chen", + "startDate": "2027-12-31", + "endDate": "2027-12-31", + "type": "milestone", + "icon": "trophy", + "description": "完成III期临床试验最终分析,向监管部门提交新药上市申请(NDA)。" + }, { "id": 6, "name": "技术选型完成", diff --git a/packageDemo/version-history.json b/packageDemo/version-history.json index bfe29c6..db38be4 100644 --- a/packageDemo/version-history.json +++ b/packageDemo/version-history.json @@ -162,5 +162,23 @@ "version": "1.2.1", "date": "2025-07-22", "notes": ["SonarQube代码质量检查问题修改"] + }, + { + "version": "1.3.0", + "date": "2025-09-12", + "notes": [ + "增加年度视图", + "Add annual timeline view", + "增加季度视图", + "Add quarterly timeline view", + "增加小时视图", + "Add hourly timeline view", + "升级TaskDrawer中DatePicker组件,接受小时的设定", + "Upgrade DatePicker component in TaskDrawer to accept hour settings", + "升级TaskDrawer中预计时间和实际时间的控件,接受小数后两位的录入", + "Upgrade the estimated time and actual time controls in TaskDrawer to accept two decimal places", + "SonarQube代码质量检查问题修改", + "SonarQube code quality inspection issue modification" + ] } ] diff --git a/src/components/DatePicker.vue b/src/components/DatePicker.vue index 5412092..f843f7a 100644 --- a/src/components/DatePicker.vue +++ b/src/components/DatePicker.vue @@ -1,22 +1,6 @@