甘特图控件DHTMLX Gantt入门使用教程【引入】:dhtmlxGantt 与Node.js(上)

news2024/11/18 11:25:09

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术(PHP,ASP.NET,Java等)简单集成,满足多种定制开发需求。

DHTMLX JavaScript UI 库所开发的 JavaScript 组件易于使用且功能丰富,非常适合任何领域和任何复杂性的解决方案,能够节省创建和维护业务应用程序的时间,提高生产力。

DHTMLX Gantt 最新下载(qun:764148812)icon-default.png?t=N3I4https://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享有超十年声誉,支持跨浏览器和跨平台,性价比高,可满足项目管理控件应用的所有需求,是较为完善的甘特图图表库。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/517426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3-黑马(三)

目录&#xff1a; &#xff08;1&#xff09;vue3-基础-计算属性 &#xff08;2&#xff09; vue3-基础-xhr-基本使用 &#xff08;3&#xff09;vue3-基础-xhr-promise改造 &#xff08;1&#xff09;vue3-基础-计算属性 上面有重复的代码&#xff0c;用计算属性&#xff0…

Kali工具集简介

Kali Linux提供了数种经过定制的专门为渗透测试设计的工具。工具都会按下图中下拉选单所示的方式按组分类聚合。了解工具是做渗透测试第一个认知。 口Information Gathering(信息收集) 这些都是侦察工具,用来收集目标网络和设备的数据。在这类工具中,从找出设备的工具到查看使…

大数据分析案例-基于高斯朴素贝叶斯算法构建良恶性肿瘤识别器

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

时间复杂度和空间复杂度的七七八八

文章目录 时间空间复杂度1. 时间空间复杂度的重要性(作用)2. 时间复杂度和大O表示法1&#xff09;算法图解2&#xff09;代码随想录3&#xff09;王道《数据结构》 3. 大O指的是最糟的情形和一般的情形1&#xff09;大O表示的是一般情况&#xff0c;并不是严格的上界2&#xff…

算法修炼之练气篇——练气四层

博主&#xff1a;命运之光 专栏&#xff1a;算法修炼之练气篇 前言&#xff1a;每天练习五道题&#xff0c;炼气篇大概会练习200道题左右&#xff0c;题目有C语言网上的题&#xff0c;也有洛谷上面的题&#xff0c;题目简单适合新手入门。&#xff08;代码都是命运之光自己写的…

创建虚拟目录和用户访问控制+虚拟目录

目录标题 虚拟目录配置文件创建配置文件对应的目录资源在创建一个虚拟目录的配置文件 用户访问控制虚拟目录创建用户访问控制权限创建配置文件中的用户资源测试tom用户测试zhangsan用户 虚拟目录 Alias 虚拟目录名称 真是目录路径为了方便对于网站资源进行灵活管理&#xff0c…

使用 MVC 模式,实现简单登录功能 (Kotlin)

先放效果图&#xff1a; 第一张是登录页面效果图。用户输入登录名和密码&#xff0c;经过后台的非空验证和固定值验证&#xff0c;跳转到首页 第二张是首页效果图。用户点击 “update” 显示用户名和密码 这里的用户名和密码是后台设置的固定值&#xff0c;整体的登录逻辑特别…

python+opencv图像形态变换

形态变换主要用于二值图像的形状操作&#xff0c;形态变换的实现原理基于数字形态学。数字形态学也称形态学&#xff0c;它主要从图像内部提取信息来描述图像形态。形态学广泛应用于视觉检测、文字识别、医学图像处理、图像压缩编码等。形态变换主要包括腐蚀、膨胀和高级形态操…

Linux aarch64架构中使用docker安装mysql8

Linux aarch64架构中使用docker安装mysql8 1、遇到问题&#xff1a; 官网下载mysql包&#xff0c;安装完成后&#xff0c;启动mysql一直显示-bash: ./mysqld: 无法执行二进制文件。 网上找了各种资料&#xff0c;但是都没有作用&#xff0c;怀疑自己操作姿势不正确&#xff…

面试题集合

Dubbo是Alibaba开源的分布式服务框架&#xff0c;它最大的特点是按照分层的方式来架构&#xff0c;使用这种方式可以使各个层之间解耦合&#xff08;或者最大限度地松耦合&#xff09;。 从服务模型的角度来看&#xff0c;Dubbo采用的是一种非常简单的模型&#xff0c;要么是提…

DNS:DNS域名解析过程及原理

一、理解IP和域名 我们首先要了解域名和IP地址的区别。 IP地址是互联网上计算机唯一的逻辑地址。 通过IP地址实现不同计算机之间的相互通信&#xff0c;每台联网计算机都需要通过IP地址来互相联系和分别。 但由于IP地址是由一串容易混淆的数字串构成&#xff0c;人们很难记忆所…

C基础 --- 因为整型提升导致的BUG

为什么会做整型提升 通常情况下&#xff0c;在对int类型的数值作运算时&#xff0c;CPU的运算速度是最快的。在x86上&#xff0c;32位算术运算的速度比16位算术运算的速度快一倍。C语言是一个注重 效率的语言&#xff0c;所以它会作整型提升&#xff0c;使得程序的运行速度尽可…

基于ChatGPT AI自动产生Shader,AI自动产生AICommand

AIEngine 基于ChatGPT AI自动产生Shader 代码地址&#xff1a;https://github.com/ManoKing/AIEngine 使用方法&#xff1a; 1&#xff0c;打开 Window/Package Manager 2&#xff0c;选择 /Add package from git URL… 3&#xff0c;添加URL: https://github.com/ManoKing/…

VMware Aria Automation Orchestrator 8.12 - 现代工作流程自动化平台

VMware Aria Automation Orchestrator 8.12 - 现代工作流程自动化平台 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-aria-automation-orchestrator/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 现代工作流程…

民谣女神唱流行,基于AI人工智能so-vits库训练自己的音色模型(叶蓓/Python3.10)

流行天后孙燕姿的音色固然是极好的&#xff0c;但是目前全网都是她的声音复刻&#xff0c;听多了难免会有些审美疲劳&#xff0c;在网络上检索了一圈&#xff0c;还没有发现民谣歌手的音色模型&#xff0c;人就是这样&#xff0c;得不到的永远在骚动&#xff0c;本次我们自己构…

艺术家林曦老师新书《无用之美》即将发售,其中甘美提前与君共享~

十多年前&#xff0c;艺术家林曦老师做了一次主题为“无用之美”的演讲&#xff0c;从那时到现在&#xff0c;也一直教授着以“美”为核心的课程。经过十年的教学、和糯糯小朋友的相处&#xff0c;林曦老师觉得自己对这个主题有了更多的感触。      “有用的世界”繁复疲惫…

科技云报道:Serverless或许没有你想象中的安全

科技云报道原创。 随着云计算技术的进一步成熟&#xff0c;Serverless已成为引领云计算下一个十年的技术热点。 Serverless能够帮助开发者无需关注服务器、按照实际使用付费且可以享受服务自动弹性伸缩&#xff0c;将更多的精力放到业务逻辑本身。据Gartner预测&#xff0c;2…

Swift AsyncThrowingStream 和 AsyncStream Demo 演示

文章目录 前言什么是 AsyncThrowingStream&#xff1f;调整现有代码以使用流什么是 AsyncStream?AsyncThrowingStreamAsyncThrowingStream 迭代调试 AsyncStream取消一个 AsyncStream结论 前言 AsyncThrowingStream 和 AsyncStream 是 Swift 5.5 中由 SE-314 引入的并发框架的…

JUC并发编程15 | Java内存模型JMM与volatile

尚硅谷&#xff08;56-70&#xff09; JMM 引入一些大厂的面试题 Java内存模型JMM是什么JMM与volatile之间的关系是什么JMM有哪些特性or它的三大特性是什么为什么要有JMM&#xff0c;它为什么出现&#xff1f;功能和作用是什么&#xff1f;happens-before 先行发生原则是什么…

LaTeX极简入门

​LaTeX是什么&#xff1f; LaTeX是一种基于ΤΕΧ的排版系统&#xff0c;由美国计算机学家莱斯利兰伯特&#xff08;Leslie Lamport&#xff09;在20世纪80年代初期开发。 LaTeX是一款开源免费&#xff0c;并且应用相当广泛的排版工具。不但能够对文字、公式、图片进行精确而复…