dhtmlxGantt 支持两种数据格式用于加载信息:
要为甘特图填充数据,可以使用 parse 或 load 方法。
gantt.init("gantt_here");
gantt.load("tasks.json");
Related sample: Basic initialization
向 Gantt 提供不正确的数据可能导致其树状结构变为循环结构,从而引发 cyclic reference error。
如果你希望直接从对象加载数据,可以使用 parse 方法:
Loading from an inline data source
var data = {
tasks:[
{id:1, text:"Project #1", start_date:"01-04-2020", duration:18},
{id:2, text:"Task #1", start_date:"02-04-2020", duration:8, parent:1},
{id:3, text:"Task #2", start_date:"11-04-2020", duration:8, parent:1}
]
};
gantt.init("gantt_here");
gantt.parse(data);
Related sample: Basic initialization
如果你的数据对象同时包含 "start_date" 和 "end_date",但日期值仅包含日期部分(如 01-12-2021,没有时间),你可能需要进行额外设置。详情请参阅 任务结束日期显示与包含结束日期。
若要从服务器获取数据,可以使用 load 方法:
gantt.html
gantt.init("gantt_here");
gantt.load("data.json");
load 方法会向指定的 URL 发送 AJAX 请求,并期望返回的数据为支持的数据格式之一。 例如:
data.json
{
"tasks":[
{"id":1, "text":"Project #1", "start_date":"01-04-2020", "duration":18},
{"id":2, "text":"Task #1", "start_date":"02-04-2020","duration":8, "parent":1},
{"id":3, "text":"Task #2", "start_date":"11-04-2020","duration":8, "parent":1}
],
"links":[
{"id":1, "source":1, "target":2, "type":"1"},
{"id":2, "source":2, "target":3, "type":"0"}
]
}
你可以在方法的第二个参数中指定格式:"json"、"xml" 或 "oldxml"。
gantt.load("data.xml", "xml");
在服务器端,你可以有一个静态数据文件,或编写脚本从数据源收集数据并以响应形式返回。 服务器端的配置取决于你使用的框架。
关于不同平台的详细说明和代码示例,请参阅 服务器端集成。
例如,在 Node.js 中,你需要设置一个处理 Gantt 发送 AJAX 数据请求的 URL 路由。
gantt.load("/data");
该路由将生成如下 JSON 响应:
app.get("/data", function(req, res){
db.query("SELECT * FROM gantt_tasks", function(err, rows){
if (err) console.log(err);
db.query("SELECT * FROM gantt_links", function(err, links){
if (err) console.log(err);
for (var i = 0; i < rows.length; i++){
rows[i].start_date = rows[i].start_date.format("YYYY-MM-DD");
rows[i].open = true;
}
res.send({ tasks:rows, links : links });
});
});
});
所有支持的数据格式可在 支持的数据格式 查看。
在数据中指定任务计划有三种方式:
未提供的属性会由另外两个属性计算得出。
Related sample: Backward planning
end_date 优先于 duration。如果同时存在三个参数,Gantt 会忽略 duration,并根据 start 和 end 日期进行计算。例如:
{
"id":"20", "text":"Project #2",
"start_date":"01-04-2025",
"duration":3,
"end_date":"05-04-2025",
"order":10,"progress":0.4,
"type": "project", "open": true
}
// 上述任务实际加载时,duration 会根据 start 和 end 日期计算:
{
"id":"20", "text":"Project #2",
"start_date":"01-04-2025",
"duration":4,
"end_date":"05-04-2025",
"order":10,"progress":0.4,
"type": "project", "open": true
}
Gantt 支持 ISO 日期格式。要启用此功能,需要重写解析和格式化日期的函数:
gantt.templates.parse_date = function(date) {
return new Date(date);
};
gantt.templates.format_date = function(date) {
return date.toISOString();
};
如果你希望动态更改日期格式,应像下面这样更新 parse_date 模板:
var cfg = gantt.config;
var strToDate = gantt.date.str_to_date(cfg.date_format, cfg.server_utc);
gantt.templates.parse_date = function(date){
return strToDate (date);
};
本节说明如何正确保存和显示任务的结束日期。
首先,考虑在处理任务日期时的两种常见场景:
由于 dhtmlxGantt 对任务结束日期的解释和存储方式,结果可能与你预期不同。
例如:
gantt.parse({ tasks: [
{
id: 1,
text: "Task 1",
start_date: "22-12-2021",
end_date: "22-12-2021"
}
]}, links:[]);
console.log(gantt.getTask(1).end_date);
// 2021年12月22日 00:00:00
console.log(gantt.getTask(1).duration);
// 0
在这种情况下,开始和结束日期指向同一时刻,因此任务持续时间为零。
gantt.config.columns = [
{name: "text", label: "Name", tree: true, width: 200, resize: true},
{name: "duration", label: "Duration", width:80, align: "center", resize: true},
{name: "start_date", label: "Start", width:80, align: "center", resize: true},
{name: "end_date", label: "Finish", width:80, align: "center", resize: true}
];
gantt.init("gantt_here");
gantt.parse({ tasks: [
{
id: 1,
text: "Task 1",
start_date: "02-04-2020",
end_date: "02-04-2020"
}
]}, links:[]);
此时,Finish(end_date)显示为 4 月 3 日,尽管任务实际上在 4 月 2 日结束。
下文将解释 Gantt 如何存储结束日期。
即使未指定时间部分(duration_unit = "day"),dhtmlxGantt 也始终将日期存储为 JavaScript Date 对象,其中包含时间组件。
结束日期的格式如下:
如果结束日期显示时不包含时间部分,可能会造成误解。在场景 2 的例子中,日期显示为 "02-04-2022 - 03-04-2022",这可能被理解为 2 天任务,而实际只有 1 天。
这是默认行为。虽然这可能令人困惑,但可以通过配置选项进行调整,后续章节将对此进行介绍。
1) 首先应避免直接更改甘特图中实际存储的任务日期。
你可能会考虑修改加载到甘特图中的任务日期,例如,将结束日期设置为 02-04-2022 23:59:59。但建议不要采用这种方式,因为这可能会导致任务工期计算和自动调度发生冲突。
我们建议使用以下方法:
2a) 如果你想调整甘特图中任务结束日期的显示格式(例如,将结束日期包含在任务工期内),可以重定义 task_end_date 模板。
下面以一个 2020 年 4 月 2 日开始、持续一天的任务为例,展示模板如何影响结束日期的显示。
默认情况下,任务的结束日期显示为 2020 年 4 月 3 日(03-04-2020 00:00:00
):
但如果你使用了 task_end_date 模板,同样的任务将显示为在 2020 年 4 月 2 日完成:
代码示例如下:
// 覆盖 columns 配置
gantt.config.columns = [
{name: "wbs", label: "#", width: 60, align: "center", template: gantt.getWBSCode},
{name: "text", label: "Name", tree: true, width: 200, resize: true},
{name: "start_date", label: "Start", width:80, align: "center", resize: true},
{name: "end_date", label: "Finish", width:80, align: "center", resize: true},
{name:"add"}
];
// 重定义模板
gantt.templates.task_end_date = function(date){
return gantt.templates.task_date(new Date(date.valueOf() - 1));
};
var gridDateToStr = gantt.date.date_to_str("%Y-%m-%d");
gantt.templates.grid_date_format = function(date, column){
if(column === "end_date"){
return gridDateToStr(new Date(date.valueOf() - 1));
}else{
return gridDateToStr(date);
}
}
gantt.init("gantt_here");
这种方式会更改任务结束日期在表格、弹窗标题以及所有显示结束日期的位置的显示。
如果你采用了 包含结束日期格式 并希望与表格中的 内联编辑 顺利配合,需要为包含结束日期的编辑操作自定义一个编辑器,如下:
// 包含结束日期的编辑器
// 使用默认编辑器,但重写 set_value/get_value 方法
var dateEditor = gantt.config.editor_types.date;
gantt.config.editor_types.end_date = gantt.mixin({
set_value: function(value, id, column, node){
var correctedValue = gantt.date.add(value, -1, "day");
return dateEditor.set_value.apply(this, [correctedValue, id, column, node]);
},
get_value: function(id, column, node) {
var selectedValue = dateEditor.get_value.apply(this, [id, column, node]);
return gantt.date.add(selectedValue, 1, "day");
},
}, dateEditor);
var textEditor = {type: "text", map_to: "text"};
var startDateEditor = {type: "date", map_to: "start_date"};
var endDateEditor = {type: "end_date", map_to: "end_date"};
var durationEditor = {type: "number", map_to: "duration", min:0, max: 100};
gantt.config.columns = [
{name: "text", label: "Name", tree: true, width: 200, editor: textEditor,
resize: true},
{name: "duration", label: "Duration", width:80, align: "center",
editor: durationEditor, resize: true},
{name: "start_date", label: "Start", width:140, align: "center",
editor: startDateEditor, resize: true},
{name: "end_date", label: "Finish", width:140, align: "center",
editor: endDateEditor, resize: true}
];
// 修改弹窗和表格模板,以包含结束日期的格式显示任务日期
gantt.templates.task_end_date = function(date){
return gantt.templates.task_date(new Date(date.valueOf() - 1));
};
var gridDateToStr = gantt.date.date_to_str("%Y-%m-%d");
gantt.templates.grid_date_format = function(date, column){
if(column === "end_date"){
return gridDateToStr(new Date(date.valueOf() - 1));
}else{
return gridDateToStr(date);
}
}
2b) 如果你的应用其他部分需要将结束日期以“包含”格式存储——即任务从 2020 年 4 月 2 日开始,持续一天,存储为 start_date: "02-04-2022", end_date: "02-04-2022"——那么需要对结束日期做额外处理:
甘特图的数据源对象包含两类主要信息:
你可以在 任务属性 文章中找到任务对象属性的完整列表。
JSON 和 XML 数据的默认日期格式为 "%d-%m-%Y %H:%i"(参见 日期格式规范)。
如需修改,请使用 date_format 配置项。
gantt.config.date_format="%Y-%m-%d";
gantt.init("gantt_here");
加载到甘特图后,start_date 和 end_date 属性会被解析为 Date 对象。
如果你的日期格式不被 date_format 支持,可以通过 parse_date 模板手动解析。
链接对象属性的完整列表请参见 链接属性 文章。
你不仅可以使用必需属性,还可以为数据项添加任意自定义属性。额外属性会被作为字符串解析并传递到客户端,你可以根据需要使用它们。
带有自定义属性的数据示例请见 这里。
如果要与数据库配合使用,建议将任务和链接分别存储在两张表中。
加载到甘特图的典型数据库结构如下:
创建两张表的 SQL 如下:
CREATE TABLE `gantt_links` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`source` int(11) NOT NULL,
`target` int(11) NOT NULL,
`type` varchar(1) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `gantt_tasks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`text` varchar(255) NOT NULL,
`start_date` datetime NOT NULL,
`duration` int(11) NOT NULL,
`progress` float NOT NULL,
`sortorder` int(11) NOT NULL,
`parent` int(11) NOT NULL,
PRIMARY KEY (`id`)
)
以下是与加载方法相关的事件流程: