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

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

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

基础代码

简单实现同步移动任务

html 复制代码
<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>

还可以实现更复杂的逻辑

html 复制代码
<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 前置任务开始日期影响后置任务完成日期 根据依赖关系的具体约束来精确更新

https://gantt.vxeui.com

相关推荐
我命由我123451 小时前
前端开发概念 - 无障碍树
javascript·css·笔记·学习·html·html5·js
ZC跨境爬虫2 小时前
跟着 MDN 学 HTML day_29:(动态构建与更新 DOM 树)
前端·javascript·ui·html·html5·媒体
搜狐技术产品小编20233 小时前
深度解析与业务实战:将 screenshot-to-code 改造为支持 React + Ant Design 的前端利器
前端·javascript·react.js·前端框架·ecmascript
weixin_471383033 小时前
set和map结构,减少O(n)复杂度
前端·javascript
倒带人生3 小时前
将 $confirm 对话框改为 a-modal 实现的通用技术方案
javascript·ant design
invicinble3 小时前
前端框架使用vue-cli (第五层:构建打包层--总体层介绍)
前端·vue.js·前端框架
前端那点事4 小时前
Vuex刷新数据丢失?4种持久化方案全覆盖,从零到项目落地(实战完整版)
前端·vue.js
前端那点事4 小时前
彻底吃透JS定时器!setTimeout/setInterval区别、坑点与最优优化方案(Vue实战)
前端·vue.js
Ruihong4 小时前
🔥Vue 转 React 实战:VuReact 实时监听开发指南
vue.js·后端·react.js