甘特图控件DHTMLX Gantt教程:用PHP:Laravel实现Gantt(上)
DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术(PHP,ASP.NET,Java等)简单集成,满足多种定制开发需求。
DHTMLX JavaScript UI 库所开发的 JavaScript 组件易于使用且功能丰富,非常适合任何领域和任何复杂性的解决方案,能够节省创建和维护业务应用程序的时间,提高生产力。
DHTMLX Gantt 最新下载(qun:764148812)
https://www.evget.com/product/4213/download
本教程介绍如何将dhtmlx甘特添加到Laravel应用程序中。
第 1 步:初始化项目
创建项目
使用 Composer 创建新应用程序:
composer create-project laravel/laravel gantt-laravel-app
下载和创建所有必要的文件应该需要一分钟。 完成所有操作后,您可以检查到目前为止一切是否正确:
cd gantt-laravel-app php artisan serve
在此步骤中,您应该获得一个默认的Laravel页面:

第 2 步:将甘特图添加到页面
添加视图
首先,我们将添加一个带有dhtmlxGantt的新页面到我们的应用程序中。 转到资源/视图文件夹并创建一个名为 gantt.blade.php 的新视图:
<!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>
在这里,我们定义了一个简单的HTML布局,从CDN添加了dhtmlxGantt的源代码,并使用init方法初始化了gantt。
请注意,我们还为文档正文和甘特图容器指定了 100% 高度。甘特图将使用其容器的大小,因此需要一些初始大小。
更改默认路由
添加新页面后,我们需要使其可从浏览器访问。在本教程中,我们将甘特图设为应用的默认页面。
转到路由/网络.php并更改默认路由:
<?phpRoute::get('/', function () {
return view('gantt');
});
再次运行应用以确保它能解决问题:

第 3 步:创建模型和迁移
所以,我们有一个空的甘特图。让我们将其连接到数据库并用数据填充它。
创建数据库
请务必更新 .env 中的数据库配置,例如:
.env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=gantt-test DB_USERNAME=root DB_PASSWORD=
下一步是创建模型类和迁移。您可以使用 Artisan 命令生成类和迁移文件:
php artisan make:model Task --migration
和
php artisan make:model Link --migration
之后,在文件夹中找到迁移并定义数据库架构。 您可以在此处找到甘特图所需的数据库架构。database/migrations
“任务”表的代码如下所示:
<?phpuse Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;class CreateTasksTable extends Migration
{
public function up()
{
Schema::create('tasks', function (Blueprint $table){
$table->increments('id');
$table->string('text');
$table->integer('duration');
$table->float('progress');
$table->dateTime('start_date');
$table->integer('parent');
$table->timestamps();
});
}public function down()
{
Schema::dropIfExists('tasks');
}
}
您将在下面找到链接表的代码:
<?phpuse Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;class CreateLinksTable extends Migration
{
public function up()
{
Schema::create('links', function (Blueprint $table) {
$table->increments('id');
$table->string('type');
$table->integer('source');
$table->integer('target');
$table->timestamps();
});
}public function down()
{
Schema::dropIfExists('links');
}
}
并运行迁移:
php artisan migrate
当我们使用它时,我们可以为我们的应用生成一些测试数据。 使用 artisan 命令生成播种器类:
php artisan make:seeder TasksTableSeeder php artisan make:seeder LinksTableSeeder
现在,创建数据库/种子文件夹,打开它并将一些数据添加到 TasksTableSeeder:
<?phpuse Illuminate\Database\Seeder;class TasksTableSeeder extends Seeder
{
public function run()
{
DB::table('tasks')->insert([
['id'=>1, 'text'=>'Project #1', 'start_date'=>'2017-04-01 00:00:00',
'duration'=>5, 'progress'=>0.8, 'parent'=>0],
['id'=>2, 'text'=>'Task #1', 'start_date'=>'2017-04-06 00:00:00',
'duration'=>4, 'progress'=>0.5, 'parent'=>1],
['id'=>3, 'text'=>'Task #2', 'start_date'=>'2017-04-05 00:00:00',
'duration'=>6, 'progress'=>0.7, 'parent'=>1],
['id'=>4, 'text'=>'Task #3', 'start_date'=>'2017-04-07 00:00:00',
'duration'=>2, 'progress'=>0, 'parent'=>1],
['id'=>5, 'text'=>'Task #1.1', 'start_date'=>'2017-04-05 00:00:00',
'duration'=>5, 'progress'=>0.34, 'parent'=>2],
['id'=>6, 'text'=>'Task #1.2', 'start_date'=>'2017-04-11 00:00:00',
'duration'=>4, 'progress'=>0.5, 'parent'=>2],
['id'=>7, 'text'=>'Task #2.1', 'start_date'=>'2017-04-07 00:00:00',
'duration'=>5, 'progress'=>0.2, 'parent'=>3],
['id'=>8, 'text'=>'Task #2.2', 'start_date'=>'2017-04-06 00:00:00',
'duration'=>4, 'progress'=>0.9, 'parent'=>3]
]);
}
}
并从 DatabaseSeeder 调用表播种机.php:
<?phpuse Illuminate\Database\Seeder;class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call(TasksTableSeeder::class);
$this->call(LinksTableSeeder::class);
}
}
之后,我们可以从命令行为数据库播种:
php artisan db:seed
定义模型类
数据通过 Eloquent 模型类进行管理。我们已经在上一步中为任务和链接生成了类。 它们已准备就绪,无需进行任何更改即可使用甘特图。
但是,我们可以做的是将 Task 类的开放属性添加到 JSON 响应中。它将在将任务加载到客户端时扩展项目树。 否则,所有分支最初都将关闭:
任务模型将如下所示:
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Task extends Model
{
protected $appends = ["open"];public function getOpenAttribute(){
return true;
}
}
链接模型不需要任何更改:
/app/Link.php
<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Link extends Model
{
}
第 4 步:加载数据
创建数据库并定义模型后,我们可以将数据加载到甘特图中。 客户端需要以下格式的日期,因此让我们创建一个控制器,其中包含生成此类 JSON 的操作:
<?php
namespace App\Http\Controllers;
use App\Task;
use App\Link;class GanttController extends Controller
{
public function get(){
$tasks = new Task();
$links = new Link();return response()->json([
"data" => $tasks->all(),
"links" => $links->all()
]);
}
}
并注册一个路由,以便客户端可以调用此操作。请注意,我们会将路由添加到 api.php routes 文件中:
<?phpuse Illuminate\Http\Request;
use App\Http\Controllers\GanttController;Route::get('/data', 'GanttController@get');
最后,从视图中调用此操作:
resources/views/gantt.blade.php
gantt.config.date_format = "%Y-%m-%d %H:%i:%s";gantt.init("gantt_here");gantt.load("/api/data");
gantt.load 将 AJAX 请求发送到指定的 URL,并期望我们之前定义的 JSON 响应。
另请注意,我们已指定date_format值。 这就是我们如何告诉甘特图数据源将使用哪种日期格式,以便客户端可以解析它们。
如果您现在检查应用程序,您应该会看到我们的甘特图中现在有任务:

第5步:保存更改
目前,我们的甘特图可以从后端读取数据。让我们让它将更改写回数据库。
客户端将在 REST 模式下工作,这意味着它将发送任务和链接操作的 POST/PUT/DELETE 请求。 您可以在此处找到请求的格式以及甘特图将使用的所有路由。
我们现在需要的是定义在两个模型上处理操作的控制器,为它们创建路由并在客户端启用数据保存。
添加控制器
让我们从控制器开始。我们将为每个模型创建一个 RESTful 资源控制器。 它将包含用于添加/删除和更新模型的方法。
任务控制器
<?php
namespace App\Http\Controllers;use Illuminate\Http\Request;
use App\Task;class TaskController extends Controller
{
public function store(Request $request){$task = new Task();$task->text = $request->text;
$task->start_date = $request->start_date;
$task->duration = $request->duration;
$task->progress = $request->has("progress") ? $request->progress : 0;
$task->parent = $request->parent;$task->save();return response()->json([
"action"=> "inserted",
"tid" => $task->id
]);
}public function update($id, Request $request){
$task = Task::find($id);$task->text = $request->text;
$task->start_date = $request->start_date;
$task->duration = $request->duration;
$task->progress = $request->has("progress") ? $request->progress : 0;
$task->parent = $request->parent;$task->save();return response()->json([
"action"=> "updated"
]);
}public function destroy($id){
$task = Task::find($id);
$task->delete();return response()->json([
"action"=> "deleted"
]);
}
}
还有一条路线:
<?phpuse Illuminate\Http\Request;Route::get('/data', 'GanttController@get');
Route::resource('task', 'TaskController');
关于此代码的一些说明:
- 当插入一个新任务时,我们在响应对象的 tid 属性中将其 id 返回给客户端
- 我们为进度参数分配默认值。 许多请求参数是可选的,这意味着如果客户端任务未分配它们,则不会将它们发送到服务器操作。
- 响应 JSON 可以具有任意数量的附加属性,它们都可以从客户端处理程序访问
现在让我们为 LinkController 实现相同的方法。
链路控制器
<?php
namespace App\Http\Controllers;use Illuminate\Http\Request;
use App\Link;class LinkController extends Controller
{
public function store(Request $request){
$link = new Link();$link->type = $request->type;
$link->source = $request->source;
$link->target = $request->target;$link->save();return response()->json([
"action"=> "inserted",
"tid" => $link->id
]);
}public function update($id, Request $request){
$link = Link::find($id);$link->type = $request->type;
$link->source = $request->source;
$link->target = $request->target;$link->save();return response()->json([
"action"=> "updated"
]);
}public function destroy($id){
$link = Link::find($id);
$link->delete();return response()->json([
"action"=> "deleted"
]);
}
}
及其路线:
<?phpuse Illuminate\Http\Request;Route::get('/data', 'GanttController@get');
Route::resource('task', 'TaskController');
Route::resource('link', 'LinkController');
在客户端启用数据保存
最后,我们将配置客户端以使用我们刚刚实现的 API:
resources/views/gantt.blade.php
gantt.config.date_format = "%Y-%m-%d %H:%i:%s";gantt.init("gantt_here");gantt.load("/api/data");var dp = new gantt.dataProcessor("/api");
dp.init(gantt);
dp.setTransactionMode("REST");
现在,您有一个完全交互式的甘特图,能够查看,添加,更新和删除任务和链接。

请查看我们的更多指南,了解 dhtmlx甘特的更多功能。
DHTMLX Gantt享有超十年声誉,支持跨浏览器和跨平台,性价比高,可满足项目管理控件应用的所有需求,是较为完善的甘特图图表库
相关文章:
甘特图控件DHTMLX Gantt教程:用PHP:Laravel实现Gantt(上)
DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术&am…...
ffmpeg-命令大全03
ffplay/mpv 查看所有的解码器 ffplay -decoders >>decoders.txt ffplay无延时无缓存播放 ffplay -fflags nobuffer -i "%1" ffplay指定size播放 ffplay -x 480 -y 270 -i "%1" ffplay指定解码器 ffplay -vcodec hevc_cuvid "%1" […...
MATLAB中太赫兹时域光谱的最大似然参数估计
目录 一、引言 二、最大似然估计的基本原理 三、MATLAB中的最大似然估计实现 四、太赫兹时域光谱的最大似然参数估计 五、结论 六、参考文献 一、引言 太赫兹波(Terahertz wave)是电磁谱中介于微波与光波之间的一段频率范围,频率大约在…...
详解MySQL的并发控制
目录 1.概述 2.事务 2.1.什么是事务 2.2.事务的隔离级别 2.2.1.三种数据一致性问题 2.2.2.四种隔离级别 2.3.如何设置隔离级别 3.锁 3.1.锁与事务的关系 3.2.分类 3.3.表锁 3.3.1.概述 3.3.2.读锁 3.3.3.写锁 3.3.4.保护机制 3.4.行锁 3.4.1.概述 3.4.2.什么…...
Android Termux安装MySQL数据库 | 公网安全远程连接【cpolar内网穿透】
文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备,尽管最初并非设计为服务器,但是随着技术的进步我们可以将Android配置为生产力工具,变成一个随身…...
SpringBoot的常见配置
SpringBoot基础配置 1. 配置文件格式问题导入1.1 修改服务器端口1.2 自动提示功能消失解决方案1.3 SpringBoot配置文件加载顺序 2. yaml问题导入2.1 yaml语法规则2.2 yaml数组数据2.3 yaml数据读取 3. 多环境开发配置问题导入3.1 多环境启动配置3.2 多环境启动命令格式3.3 多环…...
LabVIEWCompactRIO 开发指南25 实施LabVIEW FPGA代码的方法
LabVIEWCompactRIO 开发指南25 实施LabVIEW FPGA代码的方法 开始开发时,应在LabVIEW项目的FPGA目标下创建VI,以便使用LabVIEW FPGA选板进行编程,该选板是LabVIEW选板的子集,包括一些LabVIEW FPGA特定函数。 应该在仿真模式下开…...
如何利用Jmeter从0到1做一次完整的压测
压测,在很多项目中都有应用,是测试小伙伴必备的一项基本技能,刚好最近接手了一个小游戏的压测任务,一轮压测下来,颇有收获,赶紧记录下来,与大家分享一下,希望大家能少踩坑。 一、压测…...
蓝桥:前端开发笔面必刷题——Day1 数组(一)
文章目录 📋前言🎯数组中重复的数字📚题目内容✅解答 🎯两数之和📚题目内容✅解答 🎯替换空格📚题目内容✅解答 🎯二维数组中的查找📚题目内容✅解答 📝最后 …...
SQL 教程-入门基础篇
文章目录 SQL 简介SQL 语法SQL SELECT 语句SQL SELECT DISTINCT 语句SQL WHERE 子句SQL AND & OR 运算符SQL ORDER BY 关键字SQL INSERT INTO 语句SQL UPDATE 语句SQL DELETE 语句 SQL 简介 SQL(Structured Query Language)是一种用于管理和操作关系…...
循环自相关函数和谱相关密度(六)——信号的循环平稳性(循环自相关函数)原理及推导
在通信、遥测、雷达和声纳系统中,一些人工信号是一类特殊的非平稳信号,它们的非平稳性表现为周期平稳性。通信信号常用待传输信号对周期性信号的某个参数进行调制、如对正弦载波进行调幅、调频和调相,以及对周期性脉冲信号进行脉幅、脉宽和脉位调制,都会产生具有周期平稳性…...
C/C++:04. 多态和虚函数
不加virtual,只能访问成员变量,不能访问成员函数 文章目录 前言1 虚函数与多态不用虚函数的多态使用虚函数的多态 2 C虚函数注意事项 构成多态的条件C虚函数注意事项构成多态的条件什么时候声明虚函数 3 C虚析构函数的必要性总结 前言 本节阐述C中的多态…...
拿下多个定点/比亚迪要上!这项技术要「降维打击」单目感知
2008年,斯巴鲁在全球首次推出了搭载有立体视觉摄像头的主动安全解决方案,并具有紧急制动功能的“EyeSight”。2010年,斯巴鲁推出升级版的“EyeSight”,成为世界上首个可以在全车速范围内避免碰撞的量产技术系统。 2014年ÿ…...
Go 的时间操作
Go 的时间操作 1. time 包 1.1. 时间类型 Go 语言中时间类型有两种: time.Time:表示时间的类型,常见的有两种方式: time.Now():获取当前的时间time.Date():根据指定的年、月、日、时、分、秒、纳秒等创…...
ThreeJS进阶之矩阵变换
ThreeJS的矩阵变换 Three.js使用matrix编码3D变换 —— 平移(位置),旋转和缩放。Object3D的每个实例都有一个matrix,用于存储该对象的位置,旋转和比例。这里介绍如何更新对象的变换。 三维物体(Object3D) 这是Three.js中大部分对象的基类,提供了一系列的属性和方法来对…...
分布式锁概念
什么是分布式锁 方案一:SETNX EXPIRE 方案二:SETNX value值是(系统时间过期时间) 方案三:使用Lua脚本(包含SETNX EXPIRE两条指令) 方案四:SET的扩展命令(SET EX PX NX) 方案五…...
PMP课堂模拟题目及解析(第10期)
91. 在项目执行阶段,一名项目干系人要求项目经理加入一个新过程的优化。项目经理应该怎么做? A. 执行实施整体变更控制过程。 B. 与过程专家一起审查项目。 C. 将优化项目分配给团队。 D. 拒绝范围蔓延企图。 92. 项目经理要求团队提供对项目应急计…...
Arm微架构分析系列3——Arm的X计划
1. 引言 前文介绍了Arm公司近几年在移动处理器市场推出的Cortex-A系列处理器。Cortex-A系列处理器每年迭代,性能和能效不断提升,是一款非常成功的产品。但是,Arm并不满足于Cortex-A系列每年的架构小幅度升级,又推出了X计划&#x…...
Kubernetes(K8S)的基础概念
文章目录 一、Kubernetes介绍1、什么是Kubernetes?2、为什么要用K8S?3、k8s的特性 二、k8s集群架构与组件1、Master组件2、配置存储中心——etcd3、Worker Node 组件 三、k8s核心概念●Pod●Pod 控制器(五大控制器)●Label●Label选择器(Label selector )●Service…...
【Linux进阶命令 04】lsof (看看是谁动了我的文件?)
文章目录 一、简介二、lsof语法2.1 基本格式2.2 选项2.3 输出字段解释 三、常用 lsof 操作3.1 查看某文件的相关进程3.2 网络相关:-i3.3 指定进程号打开的文件:-p3.4 指定用户打开的文件:-u3.5 某进程打开的文件:-c3.6 复合查询 四…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...
