当前位置: 首页 > news >正文

甘特图控件DHTMLX Gantt教程:用PHP:Laravel实现Gantt(上)

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

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

DHTMLX Gantt 最新下载(qun:764148812)icon-default.png?t=N4HBhttps://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图表。可满足项目管理应用程序的大部分开发需求&#xff0c;具备完善的甘特图图表库&#xff0c;功能强大&#xff0c;价格便宜&#xff0c;提供丰富而灵活的JavaScript API接口&#xff0c;与各种服务器端技术&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中的最大似然估计实现 四、太赫兹时域光谱的最大似然参数估计 五、结论 六、参考文献 一、引言 太赫兹波&#xff08;Terahertz wave&#xff09;是电磁谱中介于微波与光波之间的一段频率范围&#xff0c;频率大约在…...

详解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作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…...

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代码的方法 开始开发时&#xff0c;应在LabVIEW项目的FPGA目标下创建VI&#xff0c;以便使用LabVIEW FPGA选板进行编程&#xff0c;该选板是LabVIEW选板的子集&#xff0c;包括一些LabVIEW FPGA特定函数。 应该在仿真模式下开…...

如何利用Jmeter从0到1做一次完整的压测

压测&#xff0c;在很多项目中都有应用&#xff0c;是测试小伙伴必备的一项基本技能&#xff0c;刚好最近接手了一个小游戏的压测任务&#xff0c;一轮压测下来&#xff0c;颇有收获&#xff0c;赶紧记录下来&#xff0c;与大家分享一下&#xff0c;希望大家能少踩坑。 一、压测…...

蓝桥:前端开发笔面必刷题——Day1 数组(一)

文章目录 &#x1f4cb;前言&#x1f3af;数组中重复的数字&#x1f4da;题目内容✅解答 &#x1f3af;两数之和&#x1f4da;题目内容✅解答 &#x1f3af;替换空格&#x1f4da;题目内容✅解答 &#x1f3af;二维数组中的查找&#x1f4da;题目内容✅解答 &#x1f4dd;最后 …...

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&#xff08;Structured Query Language&#xff09;是一种用于管理和操作关系…...

循环自相关函数和谱相关密度(六)——信号的循环平稳性(循环自相关函数)原理及推导

在通信、遥测、雷达和声纳系统中,一些人工信号是一类特殊的非平稳信号,它们的非平稳性表现为周期平稳性。通信信号常用待传输信号对周期性信号的某个参数进行调制、如对正弦载波进行调幅、调频和调相,以及对周期性脉冲信号进行脉幅、脉宽和脉位调制,都会产生具有周期平稳性…...

C/C++:04. 多态和虚函数

不加virtual&#xff0c;只能访问成员变量&#xff0c;不能访问成员函数 文章目录 前言1 虚函数与多态不用虚函数的多态使用虚函数的多态 2 C虚函数注意事项 构成多态的条件C虚函数注意事项构成多态的条件什么时候声明虚函数 3 C虚析构函数的必要性总结 前言 本节阐述C中的多态…...

拿下多个定点/比亚迪要上!这项技术要「降维打击」单目感知

2008年&#xff0c;斯巴鲁在全球首次推出了搭载有立体视觉摄像头的主动安全解决方案&#xff0c;并具有紧急制动功能的“EyeSight”。2010年&#xff0c;斯巴鲁推出升级版的“EyeSight”&#xff0c;成为世界上首个可以在全车速范围内避免碰撞的量产技术系统。 2014年&#xff…...

Go 的时间操作

Go 的时间操作 1. time 包 1.1. 时间类型 Go 语言中时间类型有两种&#xff1a; time.Time&#xff1a;表示时间的类型&#xff0c;常见的有两种方式&#xff1a; time.Now()&#xff1a;获取当前的时间time.Date()&#xff1a;根据指定的年、月、日、时、分、秒、纳秒等创…...

ThreeJS进阶之矩阵变换

ThreeJS的矩阵变换 Three.js使用matrix编码3D变换 —— 平移(位置),旋转和缩放。Object3D的每个实例都有一个matrix,用于存储该对象的位置,旋转和比例。这里介绍如何更新对象的变换。 三维物体(Object3D) 这是Three.js中大部分对象的基类,提供了一系列的属性和方法来对…...

分布式锁概念

什么是分布式锁 方案一&#xff1a;SETNX EXPIRE 方案二&#xff1a;SETNX value值是&#xff08;系统时间过期时间&#xff09; 方案三&#xff1a;使用Lua脚本(包含SETNX EXPIRE两条指令) 方案四&#xff1a;SET的扩展命令&#xff08;SET EX PX NX&#xff09; 方案五…...

PMP课堂模拟题目及解析(第10期)

91. 在项目执行阶段&#xff0c;一名项目干系人要求项目经理加入一个新过程的优化。项目经理应该怎么做&#xff1f; A. 执行实施整体变更控制过程。 B. 与过程专家一起审查项目。 C. 将优化项目分配给团队。 D. 拒绝范围蔓延企图。 92. 项目经理要求团队提供对项目应急计…...

Arm微架构分析系列3——Arm的X计划

1. 引言 前文介绍了Arm公司近几年在移动处理器市场推出的Cortex-A系列处理器。Cortex-A系列处理器每年迭代&#xff0c;性能和能效不断提升&#xff0c;是一款非常成功的产品。但是&#xff0c;Arm并不满足于Cortex-A系列每年的架构小幅度升级&#xff0c;又推出了X计划&#x…...

Kubernetes(K8S)的基础概念

文章目录 一、Kubernetes介绍1、什么是Kubernetes&#xff1f;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 网络相关&#xff1a;-i3.3 指定进程号打开的文件&#xff1a;-p3.4 指定用户打开的文件&#xff1a;-u3.5 某进程打开的文件&#xff1a;-c3.6 复合查询 四…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏

一、引言 在深度学习中&#xff0c;我们训练出的神经网络往往非常庞大&#xff08;比如像 ResNet、YOLOv8、Vision Transformer&#xff09;&#xff0c;虽然精度很高&#xff0c;但“太重”了&#xff0c;运行起来很慢&#xff0c;占用内存大&#xff0c;不适合部署到手机、摄…...