diff --git a/demo/App.vue b/demo/App.vue index c749cb9..5f257a1 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -41,6 +41,7 @@ const toolbarConfig = { showTimeScale: true, // 控制日|周|月时间刻度按钮组的可见性 timeScaleDimensions: ['week', 'month', 'quarter', 'year'], // 设置时间刻度按钮的展示维度,包含所有时间维度 defaultTimeScale: 'week', + showExpandCollapse: true, // 显示全部展开/折叠按钮 } // TaskList列配置 diff --git a/src/components/GanttChart.vue b/src/components/GanttChart.vue index 72e725e..182da43 100644 --- a/src/components/GanttChart.vue +++ b/src/components/GanttChart.vue @@ -37,6 +37,8 @@ const props = withDefaults(defineProps(), { onLanguageChange: undefined, onThemeChange: undefined, onFullscreenChange: undefined, + onExpandAll: undefined, + onCollapseAll: undefined, localeMessages: undefined, workingHours: () => ({ morning: { start: 8, end: 11 }, @@ -96,6 +98,8 @@ interface Props { onLanguageChange?: (lang: 'zh-CN' | 'en-US') => void onThemeChange?: (isDark: boolean) => void onFullscreenChange?: (isFullscreen: boolean) => void + onExpandAll?: () => void + onCollapseAll?: () => void /** * 自定义多语言(国际化)配置,结构参考内置 messages['zh-CN'],只需传递需要覆盖的 key 即可。 * 例如: @@ -346,6 +350,52 @@ const handleTaskCollapseChange = (task: Task) => { updateTaskTrigger.value++ } +// 全部展开任务 +const handleExpandAll = () => { + if (props.onExpandAll && typeof props.onExpandAll === 'function') { + props.onExpandAll() + } else { + // 默认行为:递归展开所有任务 + const expandAllTasks = (tasks: Task[]): void => { + tasks.forEach(task => { + if (task.children && task.children.length > 0) { + task.collapsed = false + expandAllTasks(task.children) + } + }) + } + + if (props.tasks) { + expandAllTasks(props.tasks) + // 触发Timeline重新计算 + updateTaskTrigger.value++ + } + } +} + +// 全部折叠任务 +const handleCollapseAll = () => { + if (props.onCollapseAll && typeof props.onCollapseAll === 'function') { + props.onCollapseAll() + } else { + // 默认行为:递归折叠所有任务 + const collapseAllTasks = (tasks: Task[]): void => { + tasks.forEach(task => { + if (task.children && task.children.length > 0) { + task.collapsed = true + collapseAllTasks(task.children) + } + }) + } + + if (props.tasks) { + collapseAllTasks(props.tasks) + // 触发Timeline重新计算 + updateTaskTrigger.value++ + } + } +} + // 用于强制触发Timeline重新计算的响应式值 const updateTaskTrigger = ref(0) @@ -1528,7 +1578,11 @@ function handleTaskDelete(task: Task, deleteChildren?: boolean) { :on-theme-change="props.onThemeChange" :on-fullscreen-change="props.onFullscreenChange" :on-time-scale-change="handleTimeScaleChange" + :on-expand-all="handleExpandAll" + :on-collapse-all="handleCollapseAll" @add-task="handleToolbarAddTask" + @expand-all="handleExpandAll" + @collapse-all="handleCollapseAll" /> diff --git a/src/components/GanttToolbar.vue b/src/components/GanttToolbar.vue index ada324a..313f0aa 100644 --- a/src/components/GanttToolbar.vue +++ b/src/components/GanttToolbar.vue @@ -20,6 +20,8 @@ const props = withDefaults(defineProps(), { onFullscreenChange: undefined, onSettingsConfirm: undefined, onTimeScaleChange: undefined, + onExpandAll: undefined, + onCollapseAll: undefined, }) const emit = defineEmits<{ @@ -32,6 +34,8 @@ const emit = defineEmits<{ 'theme-change': [isDark: boolean] 'fullscreen-change': [isFullscreen: boolean] 'time-scale-change': [scale: TimelineScale] + 'expand-all': [] + 'collapse-all': [] }>() // LocalStorage keys @@ -56,6 +60,8 @@ interface Props { onThemeChange?: (isDark: boolean) => void onFullscreenChange?: (isFullscreen: boolean) => void onTimeScaleChange?: (scale: TimelineScale) => void + onExpandAll?: () => void + onCollapseAll?: () => void // 外部确认接口 onSettingsConfirm?: ( type: 'theme' | 'language', @@ -140,6 +146,23 @@ const handleExportPdf = () => { } } +// 展开/折叠处理函数 +const handleExpandAll = () => { + if (props.onExpandAll && typeof props.onExpandAll === 'function') { + props.onExpandAll() + } else { + emit('expand-all') + } +} + +const handleCollapseAll = () => { + if (props.onCollapseAll && typeof props.onCollapseAll === 'function') { + props.onCollapseAll() + } else { + emit('collapse-all') + } +} + // 语言下拉菜单控制 const toggleLanguageDropdown = () => { showLanguageDropdown.value = !showLanguageDropdown.value @@ -461,6 +484,45 @@ onUnmounted(() => { + +
+ + +
+