v1.6.0 - bugfix Task拖放功能
This commit is contained in:
@@ -19,8 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
- 🔧 修复:仅删除Story层级后,子Task升级后关系线丢失问题
|
||||
- 🔧 修复:Task拖方后数据的Bug
|
||||
- 🔧 修复:修复已知问题
|
||||
- 🔧 Fixed: Issue of missing relationship lines after upgrading child Tasks when only deleting Story
|
||||
- 🔧 Fixed: Bug in Task data after dragging and dropping
|
||||
- 🔧 Fixed: Fixed issues
|
||||
|
||||
## [1.5.0] - 2025-12-13
|
||||
|
||||
@@ -511,6 +511,8 @@ const handleTaskUpdateEvent = (e: { task: Task }) => {
|
||||
|
||||
// 任务添加事件处理器
|
||||
const handleTaskAddEvent = (e: { task: Task }) => {
|
||||
// 打印全部的tasks
|
||||
console.log('当前所有任务:', tasks.value)
|
||||
const newTask = e.task
|
||||
showMessage(`Demo 任务[${newTask.name}] 已创建`, 'success')
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://nelson820125.github.io/jordium-gantt-vue3/</loc>
|
||||
<lastmod>2025-12-11</lastmod>
|
||||
<lastmod>2025-12-14</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
<priority>1.6.0</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
|
||||
@@ -388,6 +388,7 @@
|
||||
"🎉 新增:Task List行样式设置属性 - task-list-row-class-name和task-list-row-style",
|
||||
"🎉 新增:为兼容旧版本TaskListColumnConfig,提供task-list-column-render-mode属性开关,可以通过设置选择Task表格列定义方式",
|
||||
"🔧 修复:仅删除Story层级后,子Task升级后关系线丢失问题",
|
||||
"🔧 修复:Task拖方后数据的Bug",
|
||||
"🔧 修复:修复已知问题",
|
||||
"<span style=\"font-weight: bold; color: #f00;\">特别感谢 osc_85545913@gitee的使用及反馈</span>",
|
||||
"🎉 Added: Declarative definition method for Task Table columns using the TaskListColumn component",
|
||||
@@ -395,6 +396,7 @@
|
||||
"🎉 Added: Task List row style setting properties - task-list-row-class-name and task-list-row-style",
|
||||
"🎉 Added: A switch for task-list-column-render-mode attribute to choose Task Table column definition method for compatibility with older versions of TaskListColumnConfig",
|
||||
"🔧 Fixed: Issue of missing relationship lines after upgrading child Tasks when only deleting Story",
|
||||
"🔧 Fixed: Bug in Task data after dragging and dropping",
|
||||
"🔧 Fixed: Fixed issues",
|
||||
"<span style=\"font-weight: bold; color: #f00;\">Special thanks to osc_85545913@gitee for their use and feedback</span>"
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { GanttChart } from 'jordium-gantt-vue3'
|
||||
import { GanttChart, TaskListColumn } from 'jordium-gantt-vue3'
|
||||
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
|
||||
|
||||
const tasks = ref([
|
||||
@@ -123,8 +123,9 @@ const addMilestone = () => {
|
||||
startDate: newTask.value.startDate,
|
||||
progress: 0,
|
||||
type: 'milestone',
|
||||
icon: 'diamond',
|
||||
icon: 'diamond'
|
||||
});
|
||||
console.log('milestones: ', milestones.value)
|
||||
newTask.value = { name: '', startDate: '', endDate: '' };
|
||||
showAddMilestoneDialog.value = false;
|
||||
}
|
||||
@@ -148,68 +149,70 @@ const handleTaskRowMoved = async (payload: {
|
||||
newParent: Task | null
|
||||
}) => {
|
||||
const { draggedTask, targetTask, position, oldParent, newParent } = payload
|
||||
|
||||
|
||||
// 组件已自动完成任务移动、parentId更新和TaskList/Timeline同步
|
||||
// 监听此事件为完全可选,仅用于:
|
||||
|
||||
// 1. 显示自定义提示消息
|
||||
const oldParentName = oldParent?.name || '根目录'
|
||||
const newParentName = newParent?.name || '根目录'
|
||||
const positionText = position === 'after' ? '在目标任务之后' : '作为目标任务的子任务'
|
||||
alert(`任务 [${draggedTask.name}] 已从 [${oldParentName}] 移动到 [${newParentName}] (${positionText})`, 'success')
|
||||
|
||||
// 2. 调用后端 API 保存新的任务层级关系
|
||||
|
||||
// 1. 调用后端 API 保存新的任务层级关系(示例)
|
||||
// 取消注释并替换为你的实际 API 调用
|
||||
/*
|
||||
try {
|
||||
await api.updateTaskHierarchy({
|
||||
taskId: draggedTask.id,
|
||||
targetTaskId: targetTask.id,
|
||||
position: position,
|
||||
oldParentId: oldParent?.id,
|
||||
newParentId: newParent?.id,
|
||||
await fetch('/api/tasks/update-hierarchy', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
taskId: draggedTask.id,
|
||||
targetTaskId: targetTask.id,
|
||||
position: position,
|
||||
oldParentId: oldParent?.id,
|
||||
newParentId: newParent?.id,
|
||||
})
|
||||
})
|
||||
console.log('任务层级保存成功')
|
||||
} catch (error) {
|
||||
console.error('保存任务层级失败:', error)
|
||||
alert('保存失败,请刷新页面')
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// 3. 触发其他业务逻辑(如更新关联数据、记录操作日志等)
|
||||
// ...
|
||||
}
|
||||
|
||||
// 任务添加后回调
|
||||
// 注意:当use-default-drawer="true"时,组件内部已经自动添加了任务到tasks数组
|
||||
// 此回调仅用于补充业务逻辑,例如根据assignee填充assigneeName等
|
||||
const onTaskAdded = (res) => {
|
||||
// 组件已自动添加任务,这里只需要找到并更新额外字段
|
||||
const addedTask = tasks.value.find(t => t.id === res.task.id);
|
||||
if (addedTask) {
|
||||
// 使用addedTask.assignee去查找assigneeOptions的label进行赋值
|
||||
|
||||
if (addedTask && addedTask.assignee) {
|
||||
// 根据assignee值查找对应的label并赋值给assigneeName
|
||||
const assigneeOption = assigneeOptions.value.find(option => option.value === addedTask.assignee);
|
||||
if (assigneeOption) {
|
||||
addedTask.assigneeName = assigneeOption.label;
|
||||
}
|
||||
} else {
|
||||
// 使用addedTask.assignee去查找assigneeOptions的label进行赋值
|
||||
const assigneeOption = assigneeOptions.value.find(option => option.value === res.task.assignee);
|
||||
if (assigneeOption) {
|
||||
res.task.assigneeName = assigneeOption.label;
|
||||
}
|
||||
tasks.value.push(res.task);
|
||||
}
|
||||
|
||||
// 不需要手动push,组件已处理
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div style="height: 600px;">
|
||||
<GanttChart
|
||||
:tasks="tasks"
|
||||
<GanttChart
|
||||
:tasks="tasks"
|
||||
:milestones="milestones"
|
||||
:task-list-config="taskListConfig"
|
||||
:toolbar-config="toolbarConfig"
|
||||
:use-default-drawer="false"
|
||||
:use-default-drawer="true"
|
||||
:use-default-milestone-dialog="false"
|
||||
:locale-messages="customMessages"
|
||||
:allow-drag-and-resize="true"
|
||||
:enable-task-row-move="true"
|
||||
:assignee-options="assigneeOptions"
|
||||
task-list-column-render-mode="declarative"
|
||||
@task-row-moved="handleTaskRowMoved"
|
||||
@add-milestone="showAddMilestoneDialog = true"
|
||||
@task-double-click="onTaskDblclick"
|
||||
@@ -217,6 +220,16 @@ const onTaskAdded = (res) => {
|
||||
@milestone-double-click="onMilestoneDblclick"
|
||||
@task-added="onTaskAdded"
|
||||
>
|
||||
<TaskListColumn prop="name" label="任务名称" width="300">
|
||||
<template #header>
|
||||
<strong style="color: #1890ff;">任务名称 (自定义Header)</strong>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<span style="color: #52c41a;">{{ scope.row.name }}</span>
|
||||
</template>
|
||||
</TaskListColumn>
|
||||
<TaskListColumn prop="startDate" label="开始时间" width="250" />
|
||||
<TaskListColumn prop="endDate" label="结束时间" width="250" />
|
||||
</GanttChart>
|
||||
</div>
|
||||
<!-- 自定义添加任务按钮 -->
|
||||
@@ -224,7 +237,7 @@ const onTaskAdded = (res) => {
|
||||
<button class="btn btn-primary" @click="showAddTaskDrawer = true">添加任务</button>
|
||||
<button class="btn btn-primary" @click="showAddMilestoneDialog = true">添加里程碑</button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 自定义抽屉组件 (原生HTML替代 el-drawer) -->
|
||||
<div v-if="showAddTaskDrawer" class="drawer-overlay" @click="showAddTaskDrawer = false">
|
||||
<div class="drawer-container" @click.stop>
|
||||
@@ -232,35 +245,35 @@ const onTaskAdded = (res) => {
|
||||
<h3>自定义添加任务组件</h3>
|
||||
<button class="close-btn" @click="showAddTaskDrawer = false">×</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="drawer-body">
|
||||
<div class="form-item">
|
||||
<label>任务名称:</label>
|
||||
<input v-model="newTask.name" type="text" placeholder="请输入任务名称" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-item">
|
||||
<label>开始日期:</label>
|
||||
<input v-model="newTask.startDate" type="date" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-item">
|
||||
<label>结束日期:</label>
|
||||
<input v-model="newTask.endDate" type="date" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="drawer-footer">
|
||||
<button class="gantt-btn gantt-btn-primary" @click="addTask">确定</button>
|
||||
<button class="gantt-btn gantt-btn-default" @click="showAddTaskDrawer = false">取消</button>
|
||||
<button class="btn btn-primary" @click="addTask">确定</button>
|
||||
<button class="btn btn-default" @click="showAddTaskDrawer = false">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 自定义Dialog组件基于element plus -->
|
||||
<el-dialog
|
||||
title="自定义添加里程碑组件 - Element Plus"
|
||||
v-model="showAddMilestoneDialog"
|
||||
<el-dialog
|
||||
title="自定义添加里程碑组件 - Element Plus"
|
||||
v-model="showAddMilestoneDialog"
|
||||
width="400px"
|
||||
@close="newTask = { name: '', startDate: '', endDate: '' }"
|
||||
>
|
||||
@@ -280,7 +293,7 @@ const onTaskAdded = (res) => {
|
||||
<el-button @click="addMilestone">确定</el-button>
|
||||
<el-button @click="showAddMilestoneDialog = false">取消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -400,23 +413,23 @@ const onTaskAdded = (res) => {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.gantt-btn-primary {
|
||||
.btn-primary {
|
||||
background: #409eff;
|
||||
color: white;
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.gantt-btn-primary:hover {
|
||||
.btn-primary:hover {
|
||||
background: #66b1ff;
|
||||
border-color: #66b1ff;
|
||||
}
|
||||
|
||||
.gantt-btn-default {
|
||||
.btn-default {
|
||||
background: white;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.gantt-btn-default:hover {
|
||||
.btn-default:hover {
|
||||
color: #409eff;
|
||||
border-color: #409eff;
|
||||
}
|
||||
@@ -431,4 +444,4 @@ const onTaskAdded = (res) => {
|
||||
from { transform: translateX(100%); }
|
||||
to { transform: translateX(0); }
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -8,6 +8,7 @@ import TaskDrawer from './TaskDrawer.vue'
|
||||
import MilestoneDialog from './MilestoneDialog.vue'
|
||||
import { useI18n, setCustomMessages } from '../composables/useI18n'
|
||||
import { formatPredecessorDisplay } from '../utils/predecessorUtils'
|
||||
import { moveTask, findTaskParent } from '../utils/taskTreeUtils'
|
||||
import jsPDF from 'jspdf'
|
||||
import html2canvas from 'html2canvas'
|
||||
import type { Task } from '../models/classes/Task'
|
||||
@@ -641,12 +642,36 @@ const handleTaskRowMoved = (payload: {
|
||||
oldParent: Task | null
|
||||
newParent: Task | null
|
||||
}) => {
|
||||
// TaskList已经通过对象引用直接修改了props.tasks的内容
|
||||
// 但computed不会因为对象内部变化而重新计算,需要手动触发
|
||||
const { draggedTask, targetTask, position } = payload
|
||||
|
||||
if (!props.tasks) return
|
||||
|
||||
// 在 GanttChart 层面执行移动操作,直接修改原始 props.tasks
|
||||
// 这样确保修改的是正确的数据源,而不是计算属性的临时结果
|
||||
const result = moveTask(props.tasks, draggedTask.id, targetTask.id, position)
|
||||
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
|
||||
// 强制触发计算属性重新计算
|
||||
updateTaskTrigger.value++
|
||||
|
||||
// 通知 TaskList 更新父级任务数据
|
||||
nextTick(() => {
|
||||
window.dispatchEvent(new CustomEvent('task-updated', {
|
||||
detail: result.movedTask
|
||||
}))
|
||||
})
|
||||
|
||||
// 向外传递事件,让外部组件进行额外处理(完全可选)
|
||||
emit('task-row-moved', payload)
|
||||
emit('task-row-moved', {
|
||||
draggedTask: result.movedTask,
|
||||
targetTask,
|
||||
position,
|
||||
oldParent: result.oldParent,
|
||||
newParent: result.newParent,
|
||||
})
|
||||
}
|
||||
|
||||
// 全部折叠任务
|
||||
|
||||
@@ -523,29 +523,14 @@ const handleTaskRowMoved = (payload: {
|
||||
|
||||
if (!props.tasks) return
|
||||
|
||||
// 执行移动操作(直接修改 props.tasks 对象,保持引用不变)
|
||||
const result = moveTask(props.tasks, draggedTask.id, targetTask.id, position)
|
||||
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
|
||||
// moveTask 已直接修改了 props.tasks,无需手动 splice
|
||||
// 强制触发下一次更新,确保视图刷新
|
||||
nextTick(() => {
|
||||
// 更新父级任务数据(重新计算进度和日期)
|
||||
updateParentTasksData()
|
||||
|
||||
// 触发事件,通知外部组件(可选)
|
||||
// 外部可以监听此事件进行额外处理,如调用API保存、显示提示等
|
||||
// 但不需要更新 tasks,组件已自动完成
|
||||
emit('task-row-moved', {
|
||||
draggedTask: result.movedTask,
|
||||
targetTask,
|
||||
position,
|
||||
oldParent: result.oldParent,
|
||||
newParent: result.newParent,
|
||||
})
|
||||
// 直接 emit 事件给父组件(GanttChart)处理,由 GanttChart 修改原始 tasks 数据
|
||||
// 这样可以确保修改的是正确的数据源,避免修改计算属性的临时结果
|
||||
emit('task-row-moved', {
|
||||
draggedTask,
|
||||
targetTask,
|
||||
position,
|
||||
oldParent: null, // 将由 GanttChart 计算
|
||||
newParent: null, // 将由 GanttChart 计算
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user