翻譯|使用教程|編輯:顏馨|2023-05-12 11:28:27.883|閱讀 263 次
概述:本章介紹用Node.js實現(xiàn)Gantt(上),歡迎查閱~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
DHTMLX Gantt是用于跨瀏覽器和跨平臺應用程序的功能齊全的Gantt圖表。可滿足項目管理應用程序的大部分開發(fā)需求,具備完善的甘特圖圖表庫,功能強大,價格便宜,提供豐富而靈活的JavaScript API接口,與各種服務器端技術(shù)(PHP,ASP.NET,Java等)簡單集成,滿足多種定制開發(fā)需求。
DHTMLX JavaScript UI 庫所開發(fā)的 JavaScript 組件易于使用且功能豐富,非常適合任何領域和任何復雜性的解決方案,能夠節(jié)省創(chuàng)建和維護業(yè)務應用程序的時間,提高生產(chǎn)力。
甘特圖控件交流群:764148812
我們用Node.js實現(xiàn)Gantt將基于REST API,用于與服務器通信。Node.js有一套現(xiàn)成的解決方案,所以我們不必從一開始就編寫所有的代碼。我們還將使用MySQL作為數(shù)據(jù)存儲。
首先,我們將創(chuàng)建一個項目文件夾,然后添加所需的依賴項。我們將使用以下模塊:
因此,讓我們創(chuàng)建一個項目文件夾并將其命名為“dhx-gantt-app”:
mkdir dhx-gantt-app cd dhx-gantt-app
現(xiàn)在我們將創(chuàng)建 package.json 文件。我們將使用以下命令在其中指定依賴項:
npm init -y
文件準備就緒后,打開它并將上面列出的依賴項放入其中。結(jié)果將類似于這個:
{ "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”), 靜態(tài)文件(名為“公共”)和單個 HTML 頁面的文件夾。
整個項目結(jié)構(gòu)如下:
dhx-gantt-app ├── node_modules ├── server.js ├── package.json └── public └── index.html
創(chuàng)建一個名為 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+"..."); });
我們在此代碼中所做的:
在下一步中,我們將創(chuàng)建“公共”文件夾。此文件夾將包含我們應用程序的主頁 - index.html。
讓我們創(chuàng)建公用文件夾并向其中添加一個索引.html文件。然后打開 index.html 文件并填充以下內(nèi)容:
<!DOCTYPE html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <script src="http://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.js"></script> <link 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>
讓我們檢查一下我們目前得到了什么。轉(zhuǎn)到項目文件夾并從命令行運行以下命令:
node server.js
然后在瀏覽器中打開 //127.0.0.1:1337。您應該會看到一個帶有空甘特圖的頁面,如下所示:
下一步是創(chuàng)建數(shù)據(jù)庫。我們將創(chuàng)建一個簡單的數(shù)據(jù)庫,其中包含兩個用于任務和鏈接的表:
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`) );
并添加一些測試數(shù)據(jù):
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');
現(xiàn)在我們需要實現(xiàn)數(shù)據(jù)加載。
由于我們使用MySQL,因此我們需要安裝可用于訪問它的必要模塊。在本教程中,CRUD 操作將基于承諾方法實現(xiàn)。 因此,我們將使用 promise-mysql - 一個 Node.js 包,用于使用 promise 和 藍鳥承諾圖書館。
要安裝它們,我們可以使用控制臺。我們需要指定以下組件版本,因為較新的組件版本彼此不兼容或沒有舊函數(shù):
npm install bluebird@3.7.2 --save npm install promise-mysql@5.1.0 --save npm install date-format-lite@17.7.0 --save
您可以選擇任何其他適當?shù)哪K。代碼相當簡單,您可以使用一組不同的工具實現(xiàn)相同的邏輯。
客戶端需要 JSON 格式的數(shù)據(jù)。因此,我們將創(chuàng)建一個返回此類數(shù)據(jù)的路由。
正如您可能已經(jīng)提到的,數(shù)據(jù)中有“start_date”屬性,該屬性保留為日期對象。因此,它應該在 格式正確。為此,我們將使用另一個模塊 - date-format-lite。
npm install date-format-lite --save
現(xiàn)在,您應該打開 server.js 文件并使用以下內(nèi)容更新其代碼:
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); } };
我們在此代碼中所做的:
請注意,我們還添加了 open 屬性,以確保任務樹最初將展開。
現(xiàn)在,我們可以從客戶端調(diào)用此路由:
gantt.config.date_format = "%Y-%m-%d %H:%i:%s"; gantt.init("gantt_here"); gantt.load("/data");
請注意,date_format配置指定來自服務器的日期(任務start_date)的格式。
現(xiàn)在讓我們通過打開 //127.0.0.1:1337 來運行應用程序。甘特圖將加載我們之前添加到數(shù)據(jù)庫中的測試數(shù)據(jù)。
我們應該實現(xiàn)的最后一件事是數(shù)據(jù)保存。 為此,我們需要一個代碼,它將客戶端發(fā)生的更新發(fā)送回服務器。 轉(zhuǎn)到 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 發(fā)送請求來做出反應 相應的網(wǎng)址。該請求將包含將更改保存在數(shù)據(jù)庫中所需的所有參數(shù)。
由于DataProcessor是在REST模式下初始化的,因此它將對每種類型的操作使用不同的HTTP動詞。 服務器端集成一文中提供了 HTTP 謂詞列表以及請求和響應詳細信息。
好吧,我們現(xiàn)在需要做的是添加所需的路由和處理程序,這會將對客戶端所做的更改放入數(shù)據(jù)庫,放入服務器.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 }; }
我們創(chuàng)建了兩組路由:一組用于任務實體,另一組用于鏈接實體。 相應地,“/data/task”URL 將用于與 到具有任務的操作,并且“/data/link”URL將用于處理包含帶有鏈接的操作的數(shù)據(jù)的請求。
請求類型非常簡單:
響應將是一個 JSON 對象,具有執(zhí)行的操作類型或“錯誤”,以防代碼失敗。
POST 請求的響應還將包含新記錄的數(shù)據(jù)庫 ID。 它將應用于客戶端,因此可以將新項映射到數(shù)據(jù)庫實體。
就這樣。打開 //127.0.0.1:1337,您將看到一個完全可操作的甘特圖。
DHTMLX Gantt享有超十年聲譽,支持跨瀏覽器和跨平臺,性價比高,可滿足項目管理控件應用的所有需求,是較為完善的甘特圖圖表庫
甘特圖控件交流群:764148812
歡迎進群交流討論,獲取更多幫助請聯(lián)系
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn