当前位置: 首页 > news >正文

如何用 vue 甘特图组件来实现计划和实际双任务条进度展示

在项目管理中,同时展示任务的计划进度与实际进度,能够直观对比执行偏差,是项目监控的核心需求。vxe-gantt 提供了灵活的子任务视图(Subview)机制,可以轻松将单个任务拆分为“计划”和“实际”两条任务条,在同一行内并行展示,实现清晰的双进度对比。

本文将通过一个完整的示例,演示如何利用子任务视图和树形结构,将原始数据拆分为计划与实际两条记录,并分别以不同颜色和位置呈现在甘特图中。

核心实现思路

  • 数据拆分:将每个原始任务拆分为三条记录:
    • 父节点:作为容器,类型标记为 VxeGanttTaskType.Subview。
    • 计划子节点:使用计划日期(planStartDate / planEndDate),flag: 1。
    • 实际子节点:使用实际日期(actualStartDate / actualEndDate),flag: 2。
  • 树形结构:通过 treeConfig 将拆分后的数据组装为树形关系。
  • 样式区分:通过 barStyle 根据 flag 值设置不同的颜色和垂直偏移量,使两条任务条错开显示。

关键配置详解

配置项作用
treeConfig启用树形结构,将拆分后的记录按父子关系组织。
taskConfig.typeField指定类型字段,用于识别 Subview 节点。
taskBarSubviewConfig.barStyle控制子任务条样式,通过 top 偏移实现上下错位。
taskBarConfig.barStyle控制主任务条样式,根据 flag 区分计划/实际颜色。
VxeGanttTaskType.Subview标记父节点为子任务视图容器。

代码

<template><div><vxe-ganttv-bind="ganttOptions"></vxe-gantt></div></template><scriptsetup>import{reactive}from'vue'import{VxeGanttTaskType}from'vxe-gantt'importXEUtilsfrom'xe-utils'constganttOptions=reactive({border:true,height:500,loading:false,cellConfig:{height:60},treeConfig:{transform:true,rowField:'id',parentField:'parentId'},taskConfig:{startField:'start',endField:'end',typeField:'type'},taskBarSubviewConfig:{barStyle({row}){if(row.flag===1){return{style:{top:'-12px'// 偏移位置,计划于实际不重叠}}}if(row.flag===2){return{style:{top:'12px'// 偏移位置,计划于实际不重叠}}}}},taskBarConfig:{showContent:true,barStyle({row}){return{round:true,// 圆角bgColor:row.flag===1?'#40d9eff':'#31d231',// 任务条的背景颜色completedBgColor:row.flag===1?'#409eff':'#14ae14'// 已完成部分任务条的背景颜色}}},taskViewConfig:{tableStyle:{width:480}},columns:[{field:'title',title:'任务名称',minWidth:100},{field:'planStartDate',title:'计划开始时间',width:100},{field:'planEndDate',title:'计划结束时间',width:100},{field:'actualStartDate',title:'实际开始时间',width:100},{field:'actualEndDate',title:'实际结束时间',width:100}],data:[]})// 模拟后端接口constloadList=()=>{ganttOptions.loading=truesetTimeout(()=>{constlist=[{id:10001,parentId:null,title:'任务R790',planStartDate:'2024-03-03',planEndDate:'2024-03-15',actualStartDate:'2024-03-03',actualEndDate:'2024-03-12'},{id:10002,parentId:null,title:'B项目',planStartDate:'2024-03-10',planEndDate:'2024-03-25',actualStartDate:'2024-03-08',actualEndDate:'2024-03-16'},{id:10003,parentId:null,title:'C项目',planStartDate:'2024-03-20',planEndDate:'2024-04-10',actualStartDate:'2024-03-22',actualEndDate:'2024-04-01'},{id:10004,parentId:null,title:'任务D554',planStartDate:'2024-03-28',planEndDate:'2024-04-19',actualStartDate:'2024-03-28',actualEndDate:'2024-04-12'},{id:10005,parentId:null,title:'E项目',planStartDate:'2024-04-05',planEndDate:'2024-04-28',actualStartDate:'2024-04-01',actualEndDate:'2024-04-24'}]// 转成子任务视图constganttData=[]list.forEach((item)=>{constcurrRow=XEUtils.assign({},item,{type:VxeGanttTaskType.Subview})constplanRow=XEUtils.assign({},item,{id:10000000+item.id,title:'计划',parentId:item.id,start:item.planStartDate,end:item.planEndDate,flag:1})constactualRow=XEUtils.assign({},item,{id:20000000+item.id,parentId:item.id,title:'实际',start:item.actualStartDate,end:item.actualEndDate,flag:2})ganttData.push(currRow)ganttData.push(planRow)ganttData.push(actualRow)})ganttOptions.data=ganttData ganttOptions.loading=false},200)}loadList()</script>

实现要点解析

1. 数据拆分逻辑

  • 个原始任务生成三条记录:
    • 父节点:保留原始信息,type 设为 Subview,作为容器。
    • 计划子节点:使用计划日期,id 重新生成(避免与父节点冲突),parentId 指向父节点。
    • 实际子节点:使用实际日期,id 同样重新生成,parentId 指向父节点。

2. 样式错位(top 偏移)

在 taskBarSubviewConfig.barStyle 中,通过 top 属性让计划条和实际条在垂直方向上错开:

类型top 值效果
计划(flag: 1)-12px任务条向上偏移,显示在上方
实际(flag: 2)12px任务条向下偏移,显示在下方

这样两条任务条在同一行内并行显示,互不遮挡。

3. 颜色区分

通过 taskBarConfig.barStyle 返回动态样式:

类型背景色已完成颜色
计划(flag: 1)#40d9eff(蓝色系)#409eff
实际(flag: 2)#31d231(绿色系)#14ae14

通过 子任务视图(Subview) + 树形结构,vxe-gantt 提供了一种简洁而强大的方式来实现计划与实际双进度

https://gantt.vxeui.com

http://www.cnnetsun.cn/news/4261591.html

相关文章:

  • 自制高精度电池监控均衡板:从AFE选型到校准实测
  • GhostVision侧扫声呐废弃蟹笼检测数据集介绍、下载及YOLO/VOC/COCO训练格式转换
  • AI算力成本失控?从GPU利用率到精细化运营的省钱指南
  • 仿真成功率89%,真机仅12%:人形机器人“数据饥荒”背后的残酷真相
  • (LangGraph教程)0. Welcome to the course!
  • 快速幂算法精讲:从原理到实战,掌握高效指数运算与取模技巧
  • 从AI剧到互动影游:用Flask与状态机构建动态剧情应用
  • 线性规划实战:从生产优化到MATLAB/LINGO求解与灵敏度分析
  • 潜态推理与视频世界模型:从像素预测到状态演化的建模实践
  • ComfyUI与Wan2.2实现可控视频生成:背景保留与动作迁移实战
  • 蓝桥杯平面切分问题解析:从数学归纳到增量算法实现
  • 理解网络--Linux 系统是如何收发网络包的?
  • SEMI E30标准解析(二)_GEM三大控制状态——谁在控制设备?
  • 具身智能的“开发范式革命”:重塑智能算法与软件开发体系
  • 【数据安全培训】2、数据安全技术01【附全文阅读】
  • 微分方程建模实战:从SIR传染病模型到数值求解与参数优化
  • Agent的“乐高工厂”:DeepSeek Harness的微内核架构与插件化工程全景剖析
  • 9000AI的项目联营和代运营、外包团队的本质区别是什么?李家旺:核心在利益绑定
  • 012-方法学比较
  • 基于Parser解析的车辆重识别:从语义分割到精准检索的实战指南
  • 200+ 插件!这个仓库收集了几乎所有的 DeepSeek Harness 插件!
  • 从黑盒到白盒:构建模块化RAG系统的核心组件与工程实践
  • Seedance 2.5专业工具:AI视频生成如何从玩具走向生产工具
  • STM32 DAC实战指南:从基础配置到DMA任意波形输出
  • LLM生产环境部署成本拆解:从显存计算到推理框架落地实践
  • 面向开发者的AI Agent支付系统设计与安全实践
  • 朴素贝叶斯中文情感分析实战:豆瓣电影评论三分类系统
  • 学习周记实践指南:构建个人知识管理系统,对抗遗忘驱动成长
  • 三层 vs 五层定制纸箱:大件家电运输破损率与成本增量实测对比
  • 把Claude Code会话变成实时流程图:AI编程代理的可观察性探索