一、甘特图组件库
1. DHTMLX Gantt
特点与优势:
- 功能全面:提供完整的甘特图功能,包括任务管理、依赖关系显示、进度可视化等。
- 高度可配置:允许开发者根据项目需求进行定制,包括外观、交互方式等。
- 跨平台兼容性:支持多种浏览器和平台,确保在不同环境下的稳定性。
适用场景:
- 适用于需要高度定制化和扩展性的项目管理场景。
- 适用于基于不同服务器端技术和框架的Web开发项目。
使用注意事项:
- 需手动汉化,可能增加一定的工作量。
- 最新版本的部分内容收费,需考虑成本因素。
github地址:GitHub - DHTMLX/gantt: GPL version of Javascript Gantt Chart
官网:DHTMLX JS Library | JavaScript/HTML5 UI Framework | JavaScript UI Library
Demo图片示例:
数据格式文档地址:探索支持的数据格式 甘特图文档 (dhtmlx.com)
数据格式:
{
"tasks":[
{"id":"1", "text":"Project #2", "start_date":"01-04-2020", "duration":18,
"progress":0.4, "open": true},
{"id":"2", "text":"Task #1", "start_date":"02-04-2020", "duration":8,
"progress":0.6, "parent":"1"},
{"id":"3", "text":"Task #2", "start_date":"11-04-2020", "duration":8,
"progress":0.6, "parent":"1"}
],
"links":[
{"id":"1", "source":"1", "target":"2", "type":"1"},
{"id":"2", "source":"2", "target":"3", "type":"0"},
{"id":"3", "source":"3", "target":"4", "type":"0"},
{"id":"4", "source":"2", "target":"5", "type":"2"}
]
}
2. Bryntum Gantt
特点与优势:
- 基于现代Web技术:采用ES 2020编写,与现代Web开发技术无缝集成。
- 无缝集成:能够轻松集成到基于Vue.js或其他流行框架的项目中。
- 专业支持:提供付费的专业支持和服务,确保项目的顺利进行。
适用场景:
- 适用于使用Vue.js等现代框架进行Web开发的项目。
- 适用于需要高级甘特图功能和专业支持的项目管理场景。
使用注意事项:
- 需要付费购买,需考虑预算因素。
- 可能需要一定的学习成本来掌握其高级功能。
github地址:GitHub - bryntum/chronograph: A reactive state management system with novel and unique properties
官网:用于项目管理的高性能 Web 组件 (bryntum.com)
Demo图片示例:
Vue集成文档:Getting Started with Bryntum Gantt in Vue | Bryntum Gantt
数据格式文档地址:TaskStore | Bryntum Gantt
任务数数据格式:
const taskStore = new TaskStore({
data : [
{
"id" : 1000,
"name" : "Cool project",
"percentDone" : 50,
"startDate" : "2019-01-02",
"expanded" : true,
"children" : [
{
"id" : 1,
"name" : "A leaf node",
"startDate" : "2019-01-02",
"percentDone" : 50,
"duration" : 10,
}
]
}
]
});
3. Syncfusion Vue Gantt
特点与优势:
- 与Vue集成良好:与Vue框架深度集成,提供流畅的开发体验。
- 直观易用:通过直观的甘特图UI,方便处理任务、依赖项和进度。
- 功能丰富:提供多种甘特图视图、任务分组、筛选等功能。
适用场景:
- 适用于基于Vue的Web项目管理应用。
- 适用于需要结构化和可视化管理任务的项目。
使用注意事项:
- 收费产品,需考虑成本因素。
- 在集成和定制过程中可能需要一定的技术支持。
官网地址:JavaScript 甘特图 |时间轴图 |同步 (syncfusion.com)
定价:Team license for Syncfusion products
Demo图片示例:
Vue集成文档:Getting started with Vue Gantt component | Syncfusion
数据格式文档地址:Data binding in Vue Gantt component | Syncfusion
数据格式:
<template>
<div>
<ejs-gantt ref='gantt' :dataSource="data"></ejs-gantt>
</div>
</template>
<script>
import { GanttComponent } from "@syncfusion/ej2-vue-gantt";
export default {
components: {
'ejs-gantt': GanttComponent
},
data: function() {
return{
data: [
{
TaskID: 1,
TaskName: 'Project Initiation',
StartDate: new Date('04/02/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{ TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
{ TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
{ TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
]
},
{
TaskID: 5,
TaskName: 'Project Estimation',
StartDate: new Date('04/02/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{ TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
{ TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
{ TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
]
},
],
};
},
};
</script>
4. GSTC Gantt
特点与优势:
- 综合管理工具:不仅提供甘特图功能,还整合了时间表、日历等其他管理工具。
- 灵活适用:适用于多种使用场景,如项目规划、活动组织等。
- 易于使用:提供直观的用户界面和交互方式,降低使用门槛。
适用场景:
- 适用于需要综合时间管理和调度功能的项目,如预订系统、活动安排等。
- 适用于需要灵活性和多功能性的项目管理场景。
使用注意事项:
- 可扩展性可能相对有限,需根据具体需求评估是否满足要求。
- 在面对复杂项目或大规模数据时,可能需要优化性能。
地址:Home gantt-schedule-timeline-calendar javascript (typescript) component (neuronet.io)
定价:Pricing gantt-schedule-timeline-calendar javascript (typescript) component (neuronet.io)
Demo图片示例:
数据格式文档地址:Getting started gantt-schedule-timeline-calendar javascript (typescript) component (neuronet.io)
数据格式:
const itemsFromDB = [{
id: "1",
label: "Item 1",
rowId: "1",
time: {
start: GSTC.api.date("2020-01-01").startOf("day").valueOf(),
end: GSTC.api.date("2020-01-02").endOf("day").valueOf(),
},
},
{
id: "2",
label: "Item 2",
rowId: "1",
time: {
start: GSTC.api.date("2020-02-01").startOf("day").valueOf(),
end: GSTC.api.date("2020-02-02").endOf("day").valueOf(),
},
},
{
id: "3",
label: "Item 3",
rowId: "2",
time: {
start: GSTC.api.date("2020-01-15").startOf("day").valueOf(),
end: GSTC.api.date("2020-01-20").endOf("day").valueOf(),
},
},]
5. vue-ganttastic
特点与优势:
- 轻量级组件:基于Vue3的轻量级甘特图组件,易于集成和部署。
- 简单易用:提供简洁明了的API和文档,降低开发难度。
- 良好的展示效果:能够以图形化的方式清晰地展示项目进度和任务状态。
适用场景:
- 适用于简单的项目管理和任务展示需求。
- 适用于需要快速集成甘特图功能的Web应用。
使用注意事项:
- 可扩展性相对较弱,可能不适合复杂的项目管理需求。
- 在面对大规模数据或复杂交互时,可能需要额外的优化工作。
地址:Live Demos | Vue-Ganttastic (zunnzunn.github.io)
Demo图片示例:
VUE集成文档:Getting started | Vue-Ganttastic (zunnzunn.github.io)
数据格式:
<template>
<g-gantt-chart
chart-start="2021-07-12 12:00"
chart-end="2021-07-14 12:00"
precision="hour"
bar-start="myBeginDate"
bar-end="myEndDate"
>
<g-gantt-row label="My row 1" :bars="row1BarList" />
<g-gantt-row label="My row 2" :bars="row2BarList" />
</g-gantt-chart>
</template>
<script setup>
import { ref } from "vue"
const row1BarList = ref([
{
myBeginDate: "2021-07-13 13:00",
myEndDate: "2021-07-13 19:00",
ganttBarConfig: {
// each bar must have a nested ganttBarConfig object ...
id: "unique-id-1", // ... and a unique "id" property
label: "Lorem ipsum dolor"
}
}
])
const row2BarList = ref([
{
myBeginDate: "2021-07-13 00:00",
myEndDate: "2021-07-14 02:00",
ganttBarConfig: {
id: "another-unique-id-2",
hasHandles: true,
label: "Hey, look at me",
style: {
// arbitrary CSS styling for your bar
background: "#e09b69",
borderRadius: "20px",
color: "black"
}
}
}
])
</script>
二、结论
不付费使用:DHTMLX Gantt
DHTMLX Gantt作为一款功能全面的甘特图工具,在不付费的情况下即可使用其大部分核心功能,包括任务管理、依赖关系显示和进度可视化等。此外,DHTMLX Gantt提供了高度定制性,允许开发者根据项目需求调整外观和交互方式,从而满足各种特定的业务场景。同时,其良好的跨平台兼容性确保了在不同环境下的稳定运行,进一步增强了其实用性。
付费使用:Syncfusion Vue Gantt
Syncfusion Vue Gantt是一款与Vue框架深度集成的甘特图工具,提供流畅的开发体验和直观易用的界面。它具备丰富的功能,如多种甘特图视图、任务分组和筛选等,能够轻松应对复杂的任务、依赖项和进度管理需求,同时文档内容清晰。
三、DHTMLX Gantt Demo实现流程
1.引入
//7.0不支持中文
npm i dhtmlx-gantt@6 -s
2.封装组件gantt
<template>
<div ref="gantt"></div>
</template>
<script>
import { gantt } from 'dhtmlx-gantt';
import "dhtmlx-gantt/codebase/dhtmlxgantt.css";
import moment from "moment";
export default {
name: 'gantt',
props: {
tasks: {
type: Object,
default () {
return { data: [], links: [] }
}
}
},
mounted: function () {
//日期格式化
gantt.config.xml_date = "%Y-%m";
gantt.config.scale_unit = "year"; //按月显示
gantt.config.date_scale = "1"; //设置时间刻度的格式(X轴) 多个尺度
gantt.config.scale_height = 50; //设置时间刻度的高度和网格的标题
gantt.config.subscales = [
{ unit: "month", step: 1, date: "%M" }
]; //指定第二个时间刻度
//左侧是否自适应
gantt.config.autofit = true;
//左侧宽
gantt.config.grid_width = 200;
//取消连线
gantt.config.drag_links = false;
//只读
gantt.config.readonly = false;
//右侧显示列名
gantt.config.date_scale = "%Y-%m-%d";
//自动调整图表坐标轴区间用于适配task的长度
gantt.config.fit_tasks = true;
//弹窗宽
gantt.config.wide_form = false;
//汉化
gantt.locale = {
date: {
month_full: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],
day_full: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
day_short: ["日", "一", "二", "三", "四", "五", "六"]
},
labels: {
dhx_cal_today_button: "今天",
day_tab: "日",
week_tab: "周",
month_tab: "月",
new_event: "新建日程",
icon_save: "保存",
icon_cancel: "关闭",
icon_details: "详细",
icon_edit: "编辑",
icon_delete: "删除",
confirm_closing: "请确认是否撤销修改!", //Your changes will be lost, are your sure?
confirm_deleting: "是否删除计划?",
section_description: "任务内容:",
section_time: "时间范围:",
section_type: "类型",
section_text: "任务名称:",
section_color: "颜色:",
/* grid columns */
column_text: "项目节点名称",
column_start_date: "开始时间",
column_duration: "持续时间",
column_add: "",
/* link confirmation */
link: "关联",
confirm_link_deleting: "将被删除",
link_start: " (开始)",
link_end: " (结束)",
type_task: "任务",
type_project: "项目",
type_milestone: "里程碑",
minutes: "分钟",
hours: "小时",
days: "天",
weeks: "周",
months: "月",
years: "年"
}
}
//左侧显示列名
gantt.config.columns = [
{ name: "text", label: "任务名称", tree: true, width: '*' },
// { name: "start_date", label: "开始时间", align: "center" },
// { name: "end_date", label: "结束时间", align: "center" },
// {
// name: "progress", label: "进度", align: "center",
// template: function (obj) {
// return (Math.floor(obj.progress * 100)).toString() + '%'
// }
// },
// { name: "add", label: "" },
];
//弹出层
gantt.config.lightbox.sections = [
{ name: "text", height: 70, map_to: "text", type: "textarea", focus: true, width: 200 },
{ name: "time", height: 30, map_to: "auto", type: "time", time_format: ["%Y", "%m", "%d"] },
{
name: "color", height: 30, map_to: "color", type: "select", options: [
{ key: "#3db9d3", label: "蓝色" },
{ key: "#33cc33", label: "绿色" },
{ key: "#FF8247", label: "橙色" },
{ key: "#ff6633", label: "红色" }
]
},
{ name: "description", height: 70, map_to: "description", type: "textarea" }
];
//弹窗标题 日期范围
gantt.templates.task_time = function (start, end, task) {
return moment(start).format('YYYY-MM-DD') + " - " + moment(end).format('YYYY-MM-DD');
};
//弹窗标题 计划名称
gantt.templates.task_text = function (start, end, task) {
return task.text;
};
gantt.init(this.$refs.gantt);
gantt.parse(this.$props.tasks);
let this_ = this
//添加后触发
gantt.attachEvent("onAfterTaskAdd", function (id, item) {
console.log("添加后触发");
this_.changeTask();
});
//移动进度后触发
gantt.attachEvent("onAfterTaskDrag", function (id, mode, e) {
console.log("移动进度后触发");
this_.changeTask();
});
//移动任务后触发
gantt.attachEvent("onAfterTaskMove", function (id, parent, tindex) {
console.log("移动任务后触发");
this_.changeTask();
});
//删除任务后触发
gantt.attachEvent("onAfterTaskDelete", function (id, item) {
console.log("删除任务后触发");
this_.changeTask();
});
//修改任务后触发
gantt.attachEvent("onAfterTaskUpdate", function (id, item) {
console.log("修改任务后触发");
this_.changeTask();
})
//保存验证
gantt.attachEvent("onLightboxSave", function (id, item) {
if (!item.text) {
gantt.message({ type: "error", text: "请填写任务名称!" });
return false;
}
return true;
});
}
}
</script>
3.使用甘特图插件gantt
<template>
<div class="container">
<gantt class="left-container" :tasks="tasks"></gantt>
</div>
</template>
<script>
import Gantt from '@/components/Gantt.vue';
// 中文引入
// import "dhtmlx-gantt/codebase/locale/locale_cn.js";
export default {
name: 'app',
components: { Gantt },
data () {
return {
tasks: {
data: [
{
id: 1, text: "合同签订", start_date: "2021-01-01", duration: 45, order: 10,
progress: 0.4, open: true
},
{
id: 11, text: "第一次付款", start_date: "2021-03-01", duration: 45, order: 10,
progress: 0.6, parent: 1
},
{
id: 12, text: "第二次付款", start_date: "2021-12-01", duration: 45, order: 20,
progress: 0.6, parent: 1
},
{
id: 13, text: "第三次付款", start_date: "2022-01-01", duration: 45, order: 20,
progress: 0.6, parent: 1
},
{
id: 2, text: "项目实施", start_date: "2021-01-01", duration: 45, order: 20,
progress: 0.4, open: true
},
{
id: 21, text: "准备阶段", start_date: "2021-03-01", duration: 78, order: 10,
progress: 0.6, parent: 2
},
{
id: 22, text: "设计阶段", start_date: "2021-04-01", duration: 100, order: 20,
progress: 0.6, parent: 2
},
{
id: 24, text: "系统开发", start_date: "2021-06-01", duration: 80, order: 40,
progress: 1, parent: 2
},
{
id: 25, text: "系统测试", start_date: "2021-10-01", duration: 40, order: 50,
progress: 0.4, parent: 2
},
{
id: 26, text: "上线准备", start_date: "2021-12-01", duration: 45, order: 60,
progress: 0.4, parent: 2
}
],
// 脱线
links: [
// { id: 1, source: 1, target: 2, type: '0' }
]
},
}
}
}
</script>
<style>
.container {
height: 450px;
width: 100%;
}
.left-container {
overflow: hidden;
position: relative;
height: 450px;
}
</style>
4.效果图
5.使用DHTMLX Gantt的注意事项
日期处理依赖: 在使用DHTMLX Gantt之前,确保已经提前安装了
moment
日期处理npm包。moment
包是DHTMLX Gantt进行日期处理的重要依赖,请确保版本兼容且正确安装。配置准确性: 配置DHTMLX Gantt时,必须严格按照官方提供的sample或API文档进行。错误的配置可能导致功能异常或界面显示问题。
避免大版本升级: 在使用dhtmlx-gantt时,建议尽量不要轻易升级大版本。因为从版本7开始,很多API功能变为了收费项目。升级大版本可能会引入不兼容的API变动和额外的收费要求。如果确实需要升级,请务必先详细阅读升级指南,并评估潜在的影响。
四、Syncfusion Vue Gantt Demo实现流程
1.安装依赖
npm install @syncfusion/ej2-vue-gantt --save
2.可进行编辑的SyncfusionGantt Demo
<template>
<div>
<ejs-gantt ref='gantt' id="GanttContainer" :dataSource="data" :taskFields = "taskFields" :height = "height" :toolbar="toolbar" :columns = "columns" :editSettings= "editSettings"></ejs-gantt>
</div>
</template>
<script>
import { GanttComponent, Edit } from "@syncfusion/ej2-vue-gantt";
export default {
components: {
'ejs-gantt': GanttComponent
},
data: function() {
return{
data: [
{
TaskID: 1,
TaskName: 'Project Initiation',
StartDate: new Date('04/02/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{ TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
{ TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
{ TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50 },
]
},
{
TaskID: 5,
TaskName: 'Project Estimation',
StartDate: new Date('04/02/2019'),
EndDate: new Date('04/21/2019'),
subtasks: [
{ TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
{ TaskID: 7, TaskName: 'List materials', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 },
{ TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50 }
]
},
],
height: '450px',
taskFields: {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
child: 'subtasks'
},
columns: [
{ field: 'TaskID', headerText: 'Task ID', textAlign: 'Left', width: '100' },
{ field: 'TaskName', headerText: 'Task Name', width: '250' },
{ field: 'StartDate', headerText: 'Start Date', width: '150' },
{ field: 'Duration', headerText: 'Duration', width: '150' },
{ field: 'Progress', headerText: 'Progress', width: '150' },
],
toolbar: ['Edit'],
editSettings: {
allowTaskbarEditing:true
},
};
},
provide: {
gantt: [ Edit ]
}
};
</script>
<style>
@import '../node_modules/@syncfusion/ej2-base/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-calendars/styles/material.css';
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css';
@import '../node_modules/@syncfusion/ej2-lists/styles/material.css';
@import '../node_modules/@syncfusion/ej2-layouts/styles/material.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-grids/styles/material.css';
@import '../node_modules/@syncfusion/ej2-richtexteditor/styles/material.css';
@import '../node_modules/@syncfusion/ej2-treegrid/styles/material.css';
@import "../node_modules/@syncfusion/ej2-vue-gantt/styles/material.css";
</style>
3.效果图
4.使用的注意事项
- 上云需购买许可证
-
需自行配置本地化语言库
例:
<template> <div> <ejs-gantt ref='gantt' id="GanttContainer" :dataSource="data" :taskFields = "taskFields" :height = "height" locale = "de-DE"></ejs-gantt> </div> </template> <script> import Vue from "vue"; import { L10n, setCulture } from '@syncfusion/ej2-base'; import { GanttPlugin } from "@syncfusion/ej2-vue-gantt"; import { projectNewData } from './data-source.js'; setCulture('de-DE'); L10n.load({ 'de-DE': { 'gantt': { "id": "ID", "name": "名称", "startDate": "开始时间", "duration": "持续时间", "progress": "进度", } } }); Vue.use(GanttPlugin); export default { data: function() { return{ data: projectNewData, height: '450px', taskFields: { id: 'TaskID', name: 'TaskName', startDate: 'StartDate', duration: 'Duration', progress: 'Progress', child: 'subtasks' } }; } }; </script>