DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术(PHP,ASP.NET,Java等)简单集成,满足多种定制开发需求。
DHTMLX JavaScript UI 库所开发的 JavaScript 组件易于使用且功能丰富,非常适合任何领域和任何复杂性的解决方案,能够节省创建和维护业务应用程序的时间,提高生产力。
DHTMLX Gantt 最新下载(qun:764148812)https://www.evget.com/product/4213/download
我们用Node.js实现Gantt将基于REST API,用于与服务器通信。Node.js有一套现成的解决方案,所以我们不必从一开始就编写所有的代码。我们还将使用MySQL作为数据存储。
第1步:创建项目
首先,我们将创建一个项目文件夹,然后添加所需的依赖项。我们将使用以下模块:
- Express - 一个用于 Node 的微型框架.js
- 正文解析器 - 节点.js解析工具
因此,让我们创建一个项目文件夹并将其命名为“dhx-gantt-app”:
mkdir dhx-gantt-app cd dhx-gantt-app
添加依赖项
现在我们将创建 package.json 文件。我们将使用以下命令在其中指定依赖项:
npm init -y
文件准备就绪后,打开它并将上面列出的依赖项放入其中。结果将类似于这个:
{ "name": "dhx-gantt-app", "version": "1.0.2", "description": "", "main": "server.js", "dependencies": { "body-parser": "^1.19.1", "express": "^4.17.2" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node server.js" }, "keywords": [], "author": "", "license": "MIT" }
最后,我们需要使用以下命令安装添加的依赖项:
npm install
准备后端
我们将遵循一个基本的快速设置:我们将为我们的应用程序后端提供一个 js 文件(我们称之为“server.js”), 静态文件(名为“公共”)和单个 HTML 页面的文件夹。
整个项目结构如下:
dhx-gantt-app ├── node_modules ├── server.js ├── package.json └── public └── index.html
创建一个名为 server 的新文件.js并将以下代码添加到其中:
const express = require('express'); const bodyParser = require('body-parser'); const path = require('path');const port = 1337; const app = express();app.use(express.static(path.join(__dirname, "public"))); app.use(bodyParser.urlencoded({ extended: true }));app.listen(port, () =>{ console.log("Server is running on port "+port+"..."); });
我们在此代码中所做的:
- 定义了静态文件将从“公共”文件夹提供
- 将应用程序附加到本地主机的 1337 端口
在下一步中,我们将创建“公共”文件夹。此文件夹将包含我们应用程序的主页 - index.html。
第2步:将甘特图添加到页面
让我们创建公用文件夹并向其中添加一个索引.html文件。然后打开 index.html 文件并填充以下内容:
<!DOCTYPE html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"><script src="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.js"></script> <link href="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.css" rel="stylesheet"><style type="text/css"> html, body{ height:100%; padding:0px; margin:0px; overflow: hidden; }</style> </head> <body> <div id="gantt_here" style='width:100%; height:100%;'></div> <script type="text/javascript"> gantt.init("gantt_here"); </script> </body>
让我们检查一下我们目前得到了什么。转到项目文件夹并从命令行运行以下命令:
node server.js
然后在浏览器中打开 http://127.0.0.1:1337。您应该会看到一个带有空甘特图的页面,如下所示:
第 3 步:准备数据库
下一步是创建数据库。我们将创建一个简单的数据库,其中包含两个用于任务和链接的表:
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, `parent` int(11) NOT NULL, PRIMARY KEY (`id`) );
并添加一些测试数据:
INSERT INTO `gantt_tasks` VALUES ('1', 'Project #1', '2017-04-01 00:00:00', '5', '0.8', '0'); INSERT INTO `gantt_tasks` VALUES ('2', 'Task #1', '2017-04-06 00:00:00', '4', '0.5', '1'); INSERT INTO `gantt_tasks` VALUES ('3', 'Task #2', '2017-04-05 00:00:00', '6', '0.7', '1'); INSERT INTO `gantt_tasks` VALUES ('4', 'Task #3', '2017-04-07 00:00:00', '2', '0', '1'); INSERT INTO `gantt_tasks` VALUES ('5', 'Task #1.1', '2017-04-05 00:00:00', '5', '0.34', '2'); INSERT INTO `gantt_tasks` VALUES ('6', 'Task #1.2', '2017-04-11 13:22:17', '4', '0.5', '2'); INSERT INTO `gantt_tasks` VALUES ('7', 'Task #2.1', '2017-04-07 00:00:00', '5', '0.2', '3'); INSERT INTO `gantt_tasks` VALUES ('8', 'Task #2.2', '2017-04-06 00:00:00', '4', '0.9', '3');
第 4 步:加载数据
现在我们需要实现数据加载。
由于我们使用MySQL,因此我们需要安装可用于访问它的必要模块。在本教程中,CRUD 操作将基于承诺方法实现。 因此,我们将使用 promise-mysql - 一个 Node.js 包,用于使用 promise 和 蓝鸟承诺图书馆。
要安装它们,我们可以使用控制台。我们需要指定以下组件版本,因为较新的组件版本彼此不兼容或没有旧函数:
npm install bluebird@3.7.2 --save npm install promise-mysql@5.1.0 --save npm install date-format-lite@17.7.0 --save
您可以选择任何其他适当的模块。代码相当简单,您可以使用一组不同的工具实现相同的逻辑。
客户端需要 JSON 格式的数据。因此,我们将创建一个返回此类数据的路由。
正如您可能已经提到的,数据中有“start_date”属性,该属性保留为日期对象。因此,它应该在 格式正确。为此,我们将使用另一个模块 - date-format-lite。
npm install date-format-lite --save
现在,您应该打开 server.js 文件并使用以下内容更新其代码:
const express = require('express'); const bodyParser = require('body-parser'); const path = require('path');const port = 1337; const app = express();app.use(express.static(path.join(__dirname, "public"))); app.use(bodyParser.urlencoded({ extended: true }));app.listen(port, () =>{ console.log("Server is running on port "+port+"..."); });const Promise = require('bluebird'); require("date-format-lite");const mysql = require('promise-mysql'); async function serverСonfig() { const db = await mysql.createPool({ host: 'localhost', user: 'root', password: '', database: 'gantt_howto_node' }); app.get("/data", (req, res) => { Promise.all([ db.query("SELECT * FROM gantt_tasks"), db.query("SELECT * FROM gantt_links") ]).then(results => { let tasks = results[0], links = results[1];for (let i = 0; i < tasks.length; i++) { tasks[i].start_date = tasks[i].start_date.format("YYYY-MM-DD hh:mm:ss"); tasks[i].open = true; }res.send({ data: tasks, collections: { links: links } });}).catch(error => { sendResponse(res, "error", null, error); }); });function sendResponse(res, action, tid, error) {if (action == "error") console.log(error);let result = { action: action }; if (tid !== undefined && tid !== null) result.tid = tid;res.send(result); } };
我们在此代码中所做的:
- 打开了与我们的数据库的 MySql 连接
- 定义在 GET /data 请求中,我们将从任务和链接表中读取数据并格式化它们,以便它们可以在客户端上解析
请注意,我们还添加了 open 属性,以确保任务树最初将展开。
现在,我们可以从客户端调用此路由:
gantt.config.date_format = "%Y-%m-%d %H:%i:%s";gantt.init("gantt_here");gantt.load("/data");
请注意,date_format配置指定来自服务器的日期(任务start_date)的格式。
现在让我们通过打开 http://127.0.0.1:1337 来运行应用程序。甘特图将加载我们之前添加到数据库中的测试数据。
第5步:保存更改
我们应该实现的最后一件事是数据保存。 为此,我们需要一个代码,它将客户端发生的更新发送回服务器。 转到 public/index.html 并将gantt.dataProcessor添加到页面:
public/index.html gantt.config.date_format = "%Y-%m-%d %H:%i:%s";gantt.init("gantt_here");gantt.load("/data");const dp = new gantt.dataProcessor("/data"); dp.init(gantt); dp.setTransactionMode("REST");
让我们更深入地看看它扮演什么角色。
请求和响应
在每个用户操作上:添加、更改或删除新任务或链接,DataProcessor 将通过向 AJAX 发送请求来做出反应 相应的网址。该请求将包含将更改保存在数据库中所需的所有参数。
由于DataProcessor是在REST模式下初始化的,因此它将对每种类型的操作使用不同的HTTP动词。 服务器端集成一文中提供了 HTTP 谓词列表以及请求和响应详细信息。
好吧,我们现在需要做的是添加所需的路由和处理程序,这会将对客户端所做的更改放入数据库,放入服务器.js文件中。 生成的代码将相当宽敞:
// add a new task app.post("/data/task", (req, res) => { let task = getTask(req.body);db.query("INSERT INTO gantt_tasks(text, start_date, duration, progress, parent)" + " VALUES (?,?,?,?,?)", [task.text, task.start_date, task.duration, task.progress, task.parent]) .then(result => { sendResponse(res, "inserted", result.insertId); }) .catch(error => { sendResponse(res, "error", null, error); }); });// update a task app.put("/data/task/:id", (req, res) => { let sid = req.params.id, task = getTask(req.body);db.query("UPDATE gantt_tasks SET text = ?, start_date = ?, " + "duration = ?, progress = ?, parent = ? WHERE id = ?", [task.text, task.start_date, task.duration, task.progress, task.parent, sid]) .then(result => { sendResponse(res, "updated"); }) .catch(error => { sendResponse(res, "error", null, error); }); });// delete a task app.delete("/data/task/:id", (req, res) => { let sid = req.params.id; db.query("DELETE FROM gantt_tasks WHERE id = ?", [sid]) .then(result => { sendResponse(res, "deleted"); }) .catch(error => { sendResponse(res, "error", null, error); }); });// add a link app.post("/data/link", (req, res) => { let link = getLink(req.body);db.query("INSERT INTO gantt_links(source, target, type) VALUES (?,?,?)", [link.source, link.target, link.type]) .then(result => { sendResponse(res, "inserted", result.insertId); }) .catch(error => { sendResponse(res, "error", null, error); }); });// update a link app.put("/data/link/:id", (req, res) => { let sid = req.params.id, link = getLink(req.body);db.query("UPDATE gantt_links SET source = ?, target = ?, type = ? WHERE id = ?", [link.source, link.target, link.type, sid]) .then(result => { sendResponse(res, "updated"); }) .catch(error => { sendResponse(res, "error", null, error); }); });// delete a link app.delete("/data/link/:id", (req, res) => { let sid = req.params.id; db.query("DELETE FROM gantt_links WHERE id = ?", [sid]) .then(result => { sendResponse(res, "deleted"); }) .catch(error => { sendResponse(res, "error", null, error); }); });function getTask(data) { return { text: data.text, start_date: data.start_date.date("YYYY-MM-DD"), duration: data.duration, progress: data.progress || 0, parent: data.parent }; }function getLink(data) { return { source: data.source, target: data.target, type: data.type }; }
我们创建了两组路由:一组用于任务实体,另一组用于链接实体。 相应地,“/data/task”URL 将用于与 到具有任务的操作,并且“/data/link”URL将用于处理包含带有链接的操作的数据的请求。
请求类型非常简单:
- POST - 将新项目插入数据库
- PUT - 更新现有记录
- 删除 - 删除项目
响应将是一个 JSON 对象,具有执行的操作类型或“错误”,以防代码失败。
POST 请求的响应还将包含新记录的数据库 ID。 它将应用于客户端,因此可以将新项映射到数据库实体。
就这样。打开 http://127.0.0.1:1337,您将看到一个完全可操作的甘特图。
DHTMLX Gantt享有超十年声誉,支持跨浏览器和跨平台,性价比高,可满足项目管理控件应用的所有需求,是较为完善的甘特图图表库。