From 9cc769c62297f6eea4540eefd92d41566b5218eb Mon Sep 17 00:00:00 2001 From: "LINING-PC\\lining" Date: Tue, 8 Jul 2025 20:03:04 +0800 Subject: [PATCH] v1.1.0 - Trigger timeline scroll when TaskBar dragging; Add 'Day|Week|Month' timeline scale; Issues fixed. --- CHANGELOG.md | 9 + README-EN.md | 4 +- README.md | 4 +- demo/App.vue | 1 + demo/version-history.json | 5 + package-lock.json | 4 +- package.json | 2 +- src/components/GanttChart.vue | 40 +- src/components/GanttToolbar.vue | 192 +++++- src/components/MilestonePoint.vue | 163 ++++- src/components/TaskBar.vue | 348 ++++++++++- src/components/Timeline.vue | 904 ++++++++++++++++++++++++++-- src/composables/useI18n.ts | 20 + src/models/configs/ToolbarConfig.ts | 1 + src/models/types/TimelineScale.ts | 75 +++ 15 files changed, 1680 insertions(+), 92 deletions(-) create mode 100644 src/models/types/TimelineScale.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 5afa6ab..4e914b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ 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.1.0] - 2025-07-08 + +### Added +- TaskBar拖拽触发Timeline水平滑动 +- 增加日|周|月视图切换 + +### Fixed +- 问题修复 + ## [1.0.10] - 2025-07-06 ### Added diff --git a/README-EN.md b/README-EN.md index 4496cf7..68f9214 100644 --- a/README-EN.md +++ b/README-EN.md @@ -188,6 +188,7 @@ interface ToolbarConfig { showLanguage?: boolean // Show language switch button showTheme?: boolean // Show theme switch button showFullscreen?: boolean // Show fullscreen toggle button + showTimeScale?: boolean // Show time scale toggle buttons (Day|Week|Month) } ``` @@ -327,7 +328,8 @@ const toolbarConfig = { showTodayLocate: true, showExportCsv: true, showExportPdf: true, - showFullscreen: true + showFullscreen: true, + showTimeScale: true // Control visibility of Day|Week|Month time scale toggle buttons } // Custom locale messages diff --git a/README.md b/README.md index 4417abc..8631205 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,7 @@ interface ToolbarConfig { showLanguage?: boolean // 是否显示语言切换按钮 showTheme?: boolean // 是否显示主题切换按钮 showFullscreen?: boolean // 是否显示全屏切换按钮 + showTimeScale?: boolean // 是否显示时间刻度切换按钮组(日|周|月) } ``` @@ -328,7 +329,8 @@ const toolbarConfig = { showTodayLocate: true, showExportCsv: true, showExportPdf: true, - showFullscreen: true + showFullscreen: true, + showTimeScale: true // 控制日|周|月时间刻度按钮组的可见性 } // 自定义多语言配置 diff --git a/demo/App.vue b/demo/App.vue index 32dcd33..215c2d9 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -41,6 +41,7 @@ const toolbarConfig = { showLanguage: true, showTheme: true, showFullscreen: true, + showTimeScale: true, // 控制日|周|月时间刻度按钮组的可见性 } // 自定义CSV导出处理器(可选) diff --git a/demo/version-history.json b/demo/version-history.json index 4daf2be..9efee33 100644 --- a/demo/version-history.json +++ b/demo/version-history.json @@ -135,5 +135,10 @@ "Timeline中sub-task隐藏后,关系线也随之隐藏", "增强TaskBar可以存在多个前置任务" ] + }, + { + "version": "1.1.0", + "date": "2025-07-08", + "notes": ["TaskBar拖拽触发Timeline水平滑动", "增加日|周|月视图切换", "问题修复"] } ] diff --git a/package-lock.json b/package-lock.json index d69bf2a..ced9263 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jordium-gantt-vue3", - "version": "1.0.9", + "version": "1.0.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jordium-gantt-vue3", - "version": "1.0.9", + "version": "1.0.10", "license": "MIT", "dependencies": { "date-fns": "^4.1.0", diff --git a/package.json b/package.json index 97fe18e..68a4b65 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jordium-gantt-vue3", - "version": "1.0.10", + "version": "1.1.0", "type": "module", "main": "dist/jordium-gantt-vue3.cjs.js", "module": "dist/jordium-gantt-vue3.es.js", diff --git a/src/components/GanttChart.vue b/src/components/GanttChart.vue index 6380190..c8abd85 100644 --- a/src/components/GanttChart.vue +++ b/src/components/GanttChart.vue @@ -9,6 +9,7 @@ import jsPDF from 'jspdf' import html2canvas from 'html2canvas' import type { Task } from '../models/classes/Task' import type { ToolbarConfig } from '../models/configs/ToolbarConfig' +import { TimelineScale } from '../models/types/TimelineScale' import { useMessage } from '../composables/useMessage' const props = withDefaults(defineProps(), { @@ -91,6 +92,9 @@ const leftPanelWidth = ref(320) // Timeline组件的引用 const timelineRef = ref | null>(null) +// 时间刻度状态 +const currentTimeScale = ref(TimelineScale.DAY) + // TaskList的固定总长度(所有列的最小宽度之和 + 边框等额外空间) // 列宽: 300+120+120+140+140+100+100+100 = 1120px // 边框: 7个列间边框 * 1px = 7px @@ -615,9 +619,18 @@ const timelineDateRange = computed(() => { const minDate = new Date(Math.min(...startDates.map(d => d.getTime()))) const maxDate = new Date(Math.max(...endDates.map(d => d.getTime()))) - // 前后各延伸6个月 - const min = new Date(minDate.getFullYear(), minDate.getMonth() - 6, 1) - const max = new Date(maxDate.getFullYear(), maxDate.getMonth() + 6 + 1, 0) + // 日视图前后各延伸6个月 + let min = new Date(minDate.getFullYear(), minDate.getMonth() - 6, 1) + let max = new Date(maxDate.getFullYear(), maxDate.getMonth() + 6 + 1, 0) + if (currentTimeScale.value === TimelineScale.WEEK) { + // 月视图Timeline周期为往前1年~往后1年 + min = new Date(minDate.getFullYear() - 1, minDate.getMonth(), 1) + max = new Date(maxDate.getFullYear() + 1, maxDate.getMonth() + 1, 0) + } else if (currentTimeScale.value === TimelineScale.MONTH) { + // 月视图Timeline周期为往前2年~往后2年 + min = new Date(minDate.getFullYear() - 2, minDate.getMonth(), 1) + max = new Date(maxDate.getFullYear() + 2, maxDate.getMonth() + 1, 0) + } return { min, max } }) @@ -638,6 +651,25 @@ const csvExportHandler = () => { defaultExportCsv() } +// 时间刻度变化处理函数 +const handleTimeScaleChange = (scale: TimelineScale) => { + currentTimeScale.value = scale + // 通知 Timeline 组件更新时间刻度 + if (timelineRef.value) { + timelineRef.value.updateTimeScale(scale) + } +} + +// Timeline组件时间刻度变化完成后的处理函数 +const handleTimelineScaleChanged = (scale: TimelineScale) => { + // 强制重新渲染所有TaskBar,触发位置重新计算 + nextTick(() => { + // 触发强制更新,让所有TaskBar重新计算位置 + const event = new CustomEvent('timeline-scale-updated', { detail: scale }) + window.dispatchEvent(event) + }) +} + // 默认CSV导出功能 const defaultExportCsv = () => { try { @@ -1156,6 +1188,7 @@ watch( :on-language-change="props.onLanguageChange" :on-theme-change="props.onThemeChange" :on-fullscreen-change="props.onFullscreenChange" + :on-time-scale-change="handleTimeScaleChange" /> @@ -1212,6 +1245,7 @@ watch( :use-default-drawer="props.useDefaultDrawer" :on-task-delete="props.onTaskDelete" :on-milestone-save="handleMilestoneSave" + @timeline-scale-changed="handleTimelineScaleChanged" /> diff --git a/src/components/GanttToolbar.vue b/src/components/GanttToolbar.vue index 57a6508..b62e779 100644 --- a/src/components/GanttToolbar.vue +++ b/src/components/GanttToolbar.vue @@ -2,6 +2,7 @@ import { ref, onMounted, onUnmounted, computed } from 'vue' import { useI18n } from '../composables/useI18n' import type { ToolbarConfig } from '../models/configs/ToolbarConfig' +import { TimelineScale } from '../models/types/TimelineScale' import '../styles/app.css' // 语言定义 - 使用多语言系统的类型 @@ -18,6 +19,7 @@ const props = withDefaults(defineProps(), { onThemeChange: undefined, onFullscreenChange: undefined, onSettingsConfirm: undefined, + onTimeScaleChange: undefined, }) const emit = defineEmits<{ @@ -29,6 +31,7 @@ const emit = defineEmits<{ 'language-change': [lang: 'zh-CN' | 'en-US'] 'theme-change': [isDark: boolean] 'fullscreen-change': [isFullscreen: boolean] + 'time-scale-change': [scale: TimelineScale] }>() // LocalStorage keys @@ -52,6 +55,7 @@ interface Props { onLanguageChange?: (lang: 'zh-CN' | 'en-US') => void onThemeChange?: (isDark: boolean) => void onFullscreenChange?: (isFullscreen: boolean) => void + onTimeScaleChange?: (scale: TimelineScale) => void // 外部确认接口 onSettingsConfirm?: ( type: 'theme' | 'language', @@ -78,6 +82,7 @@ const currentLanguage = ref('zh') const isDarkMode = ref(getInitialTheme()) const isFullscreen = ref(false) const showLanguageDropdown = ref(false) +const currentTimeScale = ref(TimelineScale.DAY) // 翻译函数 - 使用 useI18n 提供的 getTranslation 函数 const t = (key: string): string => { @@ -261,6 +266,33 @@ const handleFullscreenToggle = () => { } } +// 时间刻度切换处理 +const handleTimeScaleChange = (scale: TimelineScale) => { + currentTimeScale.value = scale + + if (props.onTimeScaleChange && typeof props.onTimeScaleChange === 'function') { + props.onTimeScaleChange(scale) + } else { + emit('time-scale-change', scale) + } +} + +// 计算分段控制器滑块位置 +const getThumbStyle = () => { + const scaleIndex = { + [TimelineScale.MONTH]: 0, + [TimelineScale.WEEK]: 1, + [TimelineScale.DAY]: 2, + } + + const index = scaleIndex[currentTimeScale.value] || 0 + const translateX = index * 100 // 每个选项占33.33%,所以移动100%的倍数 + + return { + transform: `translateX(${translateX}%)`, + } +} + // 点击外部关闭下拉菜单 const handleClickOutside = (event: MouseEvent) => { const target = event.target as HTMLElement @@ -413,6 +445,36 @@ onUnmounted(() => {
+ +
+
+
+
+ + + +