v1.4.5 - add Task drag and drop ender TaskList
This commit is contained in:
+110
-6
@@ -12,6 +12,7 @@ import VersionHistoryDrawer from './VersionHistoryDrawer.vue'
|
||||
import HtmlContent from './HtmlContent.vue'
|
||||
import { useMessage } from '../src/composables/useMessage'
|
||||
import { useI18n } from '../src/composables/useI18n'
|
||||
import { useDemoLocale } from './useDemoLocale'
|
||||
import { getPredecessorIds, predecessorIdsToString } from '../src/utils/predecessorUtils'
|
||||
import type { Task } from '../src/models/Task'
|
||||
import type { TaskListConfig, TaskListColumnConfig } from '../src/models/configs/TaskListConfig'
|
||||
@@ -19,6 +20,7 @@ import type { TaskBarConfig } from '../src/models/configs/TaskBarConfig'
|
||||
|
||||
const { showMessage } = useMessage()
|
||||
const { t, formatTranslation } = useI18n()
|
||||
const { locale: demoLocale, messages: demoMessages, setLocale: setDemoLocale, formatMessage, getTaskTypeName, getParentName } = useDemoLocale()
|
||||
|
||||
const tasks = ref<Task[]>([])
|
||||
const milestones = ref<Task[]>([])
|
||||
@@ -182,6 +184,9 @@ const taskListConfig = computed<TaskListConfig>(() => ({
|
||||
// 控制是否允许拖拽和拉伸
|
||||
const allowDragAndResize = ref(true)
|
||||
|
||||
// 控制是否启用TaskRow拖拽移动
|
||||
const enableTaskRowMove = ref(true)
|
||||
|
||||
// TaskBar配置
|
||||
const taskBarOptions = ref({
|
||||
showAvatar: true,
|
||||
@@ -236,6 +241,17 @@ const toggleTaskBarConfig = () => {
|
||||
const showTaskClickDialog = ref(false)
|
||||
const clickedTask = ref<Task | null>(null)
|
||||
|
||||
// TaskRow Move 相关(已移除确认对话框,直接显示提示消息)
|
||||
|
||||
// 同步语言切换
|
||||
const handleLanguageChange = (lang: 'zh-CN' | 'en-US') => {
|
||||
setDemoLocale(lang)
|
||||
const languageText = lang === 'zh-CN' ? '中文' : 'English'
|
||||
showMessage(formatTranslation('languageSwitchedTo', { language: languageText }), 'info', {
|
||||
closable: true,
|
||||
})
|
||||
}
|
||||
|
||||
// 处理任务点击事件
|
||||
const handleTaskClick = (task: Task) => {
|
||||
clickedTask.value = task
|
||||
@@ -306,12 +322,7 @@ const handleAddMilestone = () => {
|
||||
showMilestoneDialog.value = true
|
||||
}
|
||||
|
||||
const handleLanguageChange = (lang: 'zh' | 'en') => {
|
||||
const languageText = lang === 'zh' ? '中文' : 'English'
|
||||
showMessage(formatTranslation('languageSwitchedTo', { language: languageText }), 'info', {
|
||||
closable: true,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const handleThemeChange = (isDark: boolean) => {
|
||||
const themeText = isDark ? t.value.darkModeText : t.value.lightModeText
|
||||
@@ -544,6 +555,86 @@ function onTimerStopped(task: Task) {
|
||||
function taskDebug(item: any) {
|
||||
// Placeholder for debugging
|
||||
}
|
||||
|
||||
// TaskRow拖拽移动事件处理器
|
||||
const handleTaskRowMoved = async (payload: {
|
||||
draggedTask: Task
|
||||
targetTask: Task
|
||||
position: 'after' | 'child' // 'after': 放在目标任务之后(同级), 'child': 作为目标任务的子任务
|
||||
oldParent: Task | null
|
||||
newParent: Task | null
|
||||
}) => {
|
||||
const { draggedTask, targetTask, position, oldParent, newParent } = payload
|
||||
|
||||
// 【注意】组件内部已自动完成数据移动,通过对象引用修改实现 TaskList 和 Timeline 的自动同步
|
||||
// 因此监听此事件是完全可选的,仅用于:
|
||||
// 1. 显示自定义提示消息
|
||||
// 2. 调用后端API保存任务层级变更
|
||||
// 3. 记录操作日志
|
||||
// 4. 触发其他业务逻辑(如更新关联数据)
|
||||
|
||||
// 构建提示消息
|
||||
const oldParentName = getParentName(oldParent)
|
||||
const newParentName = position === 'after'
|
||||
? getParentName(newParent)
|
||||
: getParentName({ type: targetTask.type, name: targetTask.name })
|
||||
|
||||
let message = ''
|
||||
const msgs = demoMessages.value.taskMoveConfirm.messages
|
||||
|
||||
if (position === 'after') {
|
||||
// 算法#1: 放置在目标任务之后
|
||||
message = formatMessage(msgs.moveAfter, {
|
||||
draggedTaskType: getTaskTypeName(draggedTask.type),
|
||||
draggedTaskName: draggedTask.name,
|
||||
targetTaskType: getTaskTypeName(targetTask.type),
|
||||
targetTaskName: targetTask.name,
|
||||
})
|
||||
} else {
|
||||
// 算法#2: 作为子任务放置
|
||||
if (oldParent && oldParent.id !== targetTask.id) {
|
||||
message = formatMessage(msgs.moveAsChild, {
|
||||
draggedTaskName: draggedTask.name,
|
||||
oldParentName,
|
||||
newParentName,
|
||||
})
|
||||
} else if (!oldParent) {
|
||||
message = formatMessage(msgs.moveAsChildNoOldParent, {
|
||||
draggedTaskName: draggedTask.name,
|
||||
newParentName,
|
||||
})
|
||||
} else {
|
||||
message = formatMessage(msgs.moveAsChildSameParent, {
|
||||
draggedTaskName: draggedTask.name,
|
||||
newParentName,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 显示移动成功提示
|
||||
const successMsg = demoMessages.value.taskMoveConfirm.messages.moveSuccess
|
||||
showMessage(`${successMsg}: ${message}`, 'success', { closable: true })
|
||||
|
||||
// ⚠️ 重要:必须更新 tasks.value 以同步 TaskList 和 Timeline
|
||||
// TaskList 已更新内部视图,但 Timeline 依赖 props.tasks
|
||||
// 此赋值会触发 GanttChart 的 watch,进而触发 Timeline 重新渲染
|
||||
tasks.value = updatedTasks
|
||||
|
||||
// 调用后端API保存任务层级变更
|
||||
// try {
|
||||
// await api.updateTaskHierarchy({
|
||||
// taskId: draggedTask.id,
|
||||
// targetTaskId: targetTask.id,
|
||||
// position: position, // 'after' 或 'child'
|
||||
// oldParentId: oldParent?.id,
|
||||
// newParentId: newParent?.id,
|
||||
// })
|
||||
// console.log('任务层级已保存到后端')
|
||||
// } catch (error) {
|
||||
// console.error('保存任务层级失败:', error)
|
||||
// showMessage('保存失败,请刷新页面', 'error', { closable: true })
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -907,6 +998,17 @@ function taskDebug(item: any) {
|
||||
{{ t.taskBarConfig.mistouch.allowDragOnClickHint }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="control-row">
|
||||
<label class="taskbar-control">
|
||||
<input v-model="enableTaskRowMove" type="checkbox" />
|
||||
<span class="taskbar-label">
|
||||
启用TaskRow拖拽移动
|
||||
</span>
|
||||
</label>
|
||||
<span class="control-hint">
|
||||
允许通过拖拽TaskRow来调整任务的层级和顺序
|
||||
</span>
|
||||
</div>
|
||||
<div class="control-row">
|
||||
<label class="control-label">
|
||||
{{ t.taskBarConfig.mistouch.dragThreshold }}:
|
||||
@@ -985,6 +1087,7 @@ function taskDebug(item: any) {
|
||||
:working-hours="workingHoursConfig"
|
||||
:use-default-milestone-dialog="true"
|
||||
:allow-drag-and-resize="allowDragAndResize"
|
||||
:enable-task-row-move="enableTaskRowMove"
|
||||
:on-export-csv="handleCustomCsvExport"
|
||||
:on-language-change="handleLanguageChange"
|
||||
:on-theme-change="handleThemeChange"
|
||||
@@ -1011,6 +1114,7 @@ function taskDebug(item: any) {
|
||||
@task-deleted="handleTaskDeleteEvent"
|
||||
@task-added="handleTaskAddEvent"
|
||||
@task-updated="handleTaskUpdateEvent"
|
||||
@task-row-moved="handleTaskRowMoved"
|
||||
>
|
||||
<template #custom-task-content="item">
|
||||
<HtmlContent
|
||||
|
||||
Reference in New Issue
Block a user