vue甘特图vxe-gantt如何实现拖拽任务条时如有已关联依赖线,同时更新依赖任务的日期的方式

109 阅读5分钟

vue甘特图vxe-gantt如何实现拖拽任务条时如有已关联依赖线,同时更新依赖任务的日期的方式

当任务关联前置任务或后置任务依赖线时,拖拽该任务时同步更新对应的起始日期和结束日期,可以通过 task-bar-drag-config.moveSetMethod 来自定义业务逻辑

extend_gantt_chart_gantt_dependency_move_update

基础代码

简单实现同步移动任务

<template>
  <div>
    <vxe-gantt v-bind="ganttOptions"></vxe-gantt>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
import { VxeGanttDependencyType } from 'vxe-gantt'
import XEUtils from 'xe-utils'

const ganttOptions = reactive({
  border: true,
  height: 600,
  rowConfig: {
    keyField: 'id' // 行主键
  },
  taskBarConfig: {
    showProgress: true, // 是否显示进度条
    showContent: true, // 是否在任务条显示内容
    moveable: true, // 是否允许拖拽任务移动日期
    resizable: true, // 是否允许拖拽任务调整日期
    linkCreatable: true, // 是否允许自定义创建依赖线
    barStyle: {
      round: true, // 圆角
      bgColor: '#fca60b', // 任务条的背景颜色
      completedBgColor: '#65c16f' // 已完成部分任务条的背景颜色
    }
  },
  taskLinkConfig: {
    isHover: true, // 当鼠标移到依赖线时,是否要高亮当前依赖线
    isCurrent: true, // 当鼠标点击依赖线时,是否要高亮当前依赖线
    isDblclickToRemove: true // 是否允许双击依赖线删除
  },
  taskViewConfig: {
    tableStyle: {
      width: 480 // 表格宽度
    }
  },
  taskBarMoveConfig: {
    isSyncLinkTask: true // 拖拽移动任务后自动更新依赖线关联任务的日期
  },
  links: [
    { from: 10001, to: 10002, type: VxeGanttDependencyType.FinishToFinish },
    { from: 10004, to: 10005, type: VxeGanttDependencyType.StartToStart },
    { from: 10005, to: 10006, type: VxeGanttDependencyType.FinishToStart },
    { from: 10013, to: 10012, type: VxeGanttDependencyType.StartToFinish }
  ],
  columns: [
    { type: 'seq', width: 70 },
    { field: 'title', title: '任务名称' },
    { field: 'start', title: '开始时间', width: 100 },
    { field: 'end', title: '结束时间', width: 100 },
    { field: 'progress', title: '进度(%)', width: 80 }
  ],
  data: [
    { id: 10001, title: '任务1', start: '2024-03-01', end: '2024-03-04', progress: 3 },
    { id: 10002, title: '任务2', start: '2024-03-03', end: '2024-03-08', progress: 10 },
    { id: 10003, title: '任务3', start: '2024-03-03', end: '2024-03-11', progress: 90 },
    { id: 10004, title: '任务4', start: '2024-03-05', end: '2024-03-11', progress: 15 },
    { id: 10005, title: '任务5', start: '2024-03-08', end: '2024-03-15', progress: 100 },
    { id: 10006, title: '任务6', start: '2024-03-10', end: '2024-03-21', progress: 5 },
    { id: 10007, title: '任务7', start: '2024-03-15', end: '2024-03-24', progress: 70 },
    { id: 10008, title: '任务8', start: '2024-03-05', end: '2024-03-15', progress: 50 },
    { id: 10009, title: '任务9', start: '2024-03-19', end: '2024-03-20', progress: 5 },
    { id: 10010, title: '任务10', start: '2024-03-12', end: '2024-03-20', progress: 10 },
    { id: 10011, title: '任务11', start: '2024-03-01', end: '2024-03-08', progress: 90 },
    { id: 10012, title: '任务12', start: '2024-03-03', end: '2024-03-06', progress: 60 },
    { id: 10013, title: '任务13', start: '2024-03-02', end: '2024-03-05', progress: 50 },
    { id: 10014, title: '任务14', start: '2024-03-04', end: '2024-03-15', progress: 0 },
    { id: 10015, title: '任务15', start: '2024-03-01', end: '2024-03-05', progress: 30 }
  ]
})
</script>

还可以实现更复杂的逻辑

<template>
  <div>
    <vxe-gantt ref="ganttRef" v-bind="ganttOptions" @task-bar-drag-end="onTaskDragEnd"></vxe-gantt>
  </div>
</template>

<script setup>
import { reactive, ref } from 'vue'
import { VxeGanttDependencyType } from 'vxe-gantt'
import XEUtils from 'xe-utils'

const ganttRef = ref(null)

const ganttOptions = reactive({
  // ...(保持原有配置)
  taskBarMoveConfig: {
    // 自定义拖拽结束时任务日期被赋值的方法
    async moveSetMethod ({ row, startValue, endValue, offsetSize, linkInfo }) {
      const $gantt = ganttRef.value
      if (!$gantt) {
        return
      }
      const { allLinks, allRows } = linkInfo
      console.log('关联连接线:', allLinks, '对应行:', allRows)

      row.start = startValue
      row.end = endValue
      // 实现拖拽任务后,关联任务自动同步更新日期
      allRows.forEach(currRow => {
        if (row !== currRow) {
          currRow.start = XEUtils.toDateString(XEUtils.getWhatDay(currRow.start, offsetSize), 'yyyy-MM-dd')
          currRow.end = XEUtils.toDateString(XEUtils.getWhatDay(currRow.end, offsetSize), 'yyyy-MM-dd')
        }
      })

      // 获取所有关联线
      // allLinks.forEach((linkItem, i) => {
      //   // 取出连接线起始对应的行
      //   const linkFromRow = $gantt.getRowById(linkItem.from)
      //   // 取出连接线结束对应的行
      //   const linkToRow = $gantt.getRowById(linkItem.to)
      //   // 判断线类型
      //   switch (linkItem.type) {
      //     case VxeGanttDependencyType.FinishToStart: {
      //       // 实现拖拽任务后,关联任务自动同步更新日期
      //       if (linkFromRow) {
      //         linkFromRow.start = XEUtils.toDateString(XEUtils.getWhatDay(linkFromRow.start, offsetSize), 'yyyy-MM-dd')
      //         linkFromRow.end = XEUtils.toDateString(XEUtils.getWhatDay(linkFromRow.end, offsetSize), 'yyyy-MM-dd')
      //       }
      //       break
      //     }
      //     case VxeGanttDependencyType.StartToFinish : {
      //       // 实现拖拽任务后,关联任务自动同步更新日期
      //       if (linkFromRow) {
      //         linkFromRow.start = XEUtils.toDateString(XEUtils.getWhatDay(linkFromRow.start, offsetSize), 'yyyy-MM-dd')
      //         linkFromRow.end = XEUtils.toDateString(XEUtils.getWhatDay(linkFromRow.end, offsetSize), 'yyyy-MM-dd')
      //       }
      //       break
      //     }
      //     case VxeGanttDependencyType.StartToStart : {
      //       // 实现拖拽任务后,关联任务自动同步更新日期
      //       if (linkFromRow) {
      //         linkFromRow.start = XEUtils.toDateString(XEUtils.getWhatDay(linkFromRow.start, offsetSize), 'yyyy-MM-dd')
      //         linkFromRow.end = XEUtils.toDateString(XEUtils.getWhatDay(linkFromRow.end, offsetSize), 'yyyy-MM-dd')
      //       }
      //       break
      //     }
      //     case VxeGanttDependencyType.FinishToFinish : {
      //       // 实现拖拽任务后,关联任务自动同步更新日期
      //       if (linkFromRow) {
      //         linkFromRow.start = XEUtils.toDateString(XEUtils.getWhatDay(linkFromRow.start, offsetSize), 'yyyy-MM-dd')
      //         linkFromRow.end = XEUtils.toDateString(XEUtils.getWhatDay(linkFromRow.end, offsetSize), 'yyyy-MM-dd')
      //       }
      //       break
      //     }
      //   }
      // })
    }
  },
  // ...(保持原有数据配置)
})

// 监听拖拽事件,执行其他业务逻辑(如保存到后端)
const onTaskDragEnd = ({ row, startValue, endValue }) => {
  // 可以在这里保存更新后的任务数据,或者执行其他业务逻辑
  console.log('任务拖拽完成', { row, startValue, endValue })
  
  // 可选:触发数据更新到后端
  // updateTaskToBackend(row)
}
</script>

依赖类型说明

依赖类型原逻辑缺陷优化后逻辑
FinishToStart前置任务结束日期推迟,后置任务应该整体推迟?❌ 应该是后置任务的开始日期=前置任务的结束日期仅更新后置任务的开始日期,保持持续时间不变
StartToStart同时开始的任务,拖拽一个不应该导致另一个结束日期整体偏移保持两个任务的结束日期相对不变,仅调整开始日期
FinishToFinish两个任务同时结束,拖拽一个不应该影响另一个的开始日期保持两个任务的开始日期相对不变,仅调整结束日期
StartToFinish前置任务开始日期影响后置任务完成日期根据依赖关系的具体约束来精确更新

gantt.vxeui.com