v1.2.0 - Add TaskContextMenu & new features; TaskDrawer is uniformly managed by GanttChart.

This commit is contained in:
LINING-PC\lining
2025-07-22 00:07:09 +08:00
parent 9cc769c622
commit 064eba945d
20 changed files with 2084 additions and 242 deletions
+62 -7
View File
@@ -2,6 +2,7 @@
import { ref, computed, onUnmounted, onMounted, nextTick, watch } from 'vue'
import type { Task } from '../models/classes/Task'
import { TimelineScale } from '../models/types/TimelineScale'
import TaskContextMenu from './TaskContextMenu.vue'
interface Props {
task: Task
@@ -34,9 +35,14 @@ const emit = defineEmits([
'update:task',
'bar-mounted',
'dblclick',
'drag-end', // 新增
'resize-end', // 新增
'scroll-to-position', // 新增:半圆点击定位事件
'drag-end',
'resize-end',
'scroll-to-position',
'start-timer',
'stop-timer',
'add-predecessor',
'add-successor',
'delete',
])
// 日期工具函数 - 处理时区安全的日期创建和操作
@@ -224,9 +230,7 @@ const taskStatus = computed(() => {
})
// 判断是否已完成
const isCompleted = computed(() => {
return (props.task.progress || 0) >= 100
})
const isCompleted = computed(() => (props.task.progress || 0) >= 100)
// 计算完成部分的宽度
const progressWidth = computed(() => {
@@ -438,10 +442,14 @@ onMounted(() => {
window.addEventListener('timeline-scale-updated', handleTimelineScaleUpdate)
window.addEventListener('timeline-force-recalculate', handleForceRecalculate)
// 监听全局关闭菜单事件
window.addEventListener('close-all-taskbar-menus', closeContextMenu)
// 清理函数
onUnmounted(() => {
window.removeEventListener('timeline-scale-updated', handleTimelineScaleUpdate)
window.removeEventListener('timeline-force-recalculate', handleForceRecalculate)
window.removeEventListener('close-all-taskbar-menus', closeContextMenu)
})
})
@@ -965,7 +973,41 @@ const calculatePositionFromTimelineData = (
return cumulativePosition // 如果没找到,返回累计位置
}
// ...existing code...
// 处理右键菜单
const contextMenuVisible = ref(false)
const contextMenuPosition = ref({ x: 0, y: 0 })
const contextMenuTask = computed(() => props.task)
function handleContextMenu(event: MouseEvent) {
// 先广播关闭所有TaskBar菜单
window.dispatchEvent(new CustomEvent('close-all-taskbar-menus'))
if (props.task.type !== 'task' && props.task.type !== 'story') {
// 为了排除里程碑类型
event.preventDefault()
contextMenuVisible.value = false
return
}
event.preventDefault()
contextMenuVisible.value = true
contextMenuPosition.value = { x: event.clientX, y: event.clientY }
}
function closeContextMenu() {
contextMenuVisible.value = false
}
const handleTaskDelete = (task: Task, deleteChildren?: boolean) => {
// 触发删除事件
emit('delete', task, deleteChildren)
closeContextMenu()
}
// 监听全局关闭菜单事件
onMounted(() => {
window.addEventListener('close-all-taskbar-menus', closeContextMenu)
})
onUnmounted(() => {
window.removeEventListener('close-all-taskbar-menus', closeContextMenu)
})
</script>
<template>
@@ -989,6 +1031,7 @@ const calculatePositionFromTimelineData = (
'short-task-bar': isShortTaskBar,
'overflow-effect': needsOverflowEffect,
}"
@contextmenu="handleContextMenu"
@dblclick="handleTaskBarDoubleClick"
>
<!-- 父级任务的标签 -->
@@ -1049,6 +1092,18 @@ const calculatePositionFromTimelineData = (
@mousedown="handleBubbleMouseDown"
@click="handleBubbleClick"
></div>
<TaskContextMenu
:visible="contextMenuVisible"
:task="contextMenuTask"
:position="contextMenuPosition"
@close="closeContextMenu"
@start-timer="$emit('start-timer', props.task)"
@stop-timer="$emit('stop-timer', props.task)"
@add-predecessor="$emit('add-predecessor', props.task)"
@add-successor="$emit('add-successor', props.task)"
@delete="handleTaskDelete"
/>
</div>
<!-- Tooltip 弹窗 -->