在项目中需要使用甘特图插件,在网上就找到了dhtmlx-gantt
,下面是使用教程
下载插件:
npm install dhtmlx-gantt -save
<template>
<div class="container">
<div class="select-wrap">
<el-select v-model="value" placeholder="请选择" @change="selectChange">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</div>
<div ref="gantt" class="gantt-container"></div>
</div>
</template>
<script>
import {
gantt
} from 'dhtmlx-gantt';
import "dhtmlx-gantt/codebase/dhtmlxgantt.css"
export default {
name: 'gantt',
data() {
return {
tasks: {
data: []
},
options: [{
value: '1',
label: '全部'
}, {
value: '2',
label: '完成'
}, {
value: '3',
label: '正常'
}, {
value: '4',
label: '异常'
}, {
value: '5',
label: '未启动'
}],
value: '1'
}
},
methods: {
//开始时间-结束时间参数
DateDifference: function(strDateStart, strDateEnd) {
var begintime_ms = Date.parse(new Date(strDateStart.replace(/-/g, '/'))) //begintime 为开始时间
var endtime_ms = Date.parse(new Date(strDateEnd.replace(/-/g, '/'))) // endtime 为结束时间
var date3 = endtime_ms - begintime_ms //时间差的毫秒数
var days = Math.floor(date3 / (24 * 3600 * 1000))
return days
},
initData: function() {
this.tasks.data = [{
id: 1,
text: '概念设计',
start_date: '2020-04-08',
duration: 10,
open: true, //默认打开,
toolTipsTxt: 'xxx项目概念设计',
progress: 0.6,
status: "parent"
},
{
toolTipsTxt: 'xxx项目-项目启动会',
text: '项目启动会-外部', // 任务名
start_date: '2020-04-08', // 开始时间
id: 11, // 任务id
duration: 3, // 任务时长,从start_date开始计算
parent: 1, // 父任务ID
type: 1,
progress: 0.5,
status: "yellow"
},
{
toolTipsTxt: 'xxx项目-项目启动会议',
text: '项目启动会-内部',
start_date: '2020-04-11',
id: 12,
duration: 2,
parent: 1,
type: 2,
progress: 0.6,
status: "pink"
},
{
toolTipsTxt: 'xxx项目开工会',
text: '项目开工会',
start_date: '2020-04-13',
id: 13,
duration: 4,
parent: 1,
type: 3,
progress: 1,
status: "green"
}, {
toolTipsTxt: 'xxx项目-项目分析',
text: '项目分析',
start_date: '2020-04-13',
id: 14,
duration: 4,
parent: 1,
type: 4,
progress: 0.6,
status: "popular"
},
{
id: 2,
text: '方案设计',
start_date: '2020-04-08',
duration: 8,
open: true,
toolTipsTxt: 'xxx方案设计',
state: 'default',
// color:"#409EFF", //设置颜色
progress: 0.6,
status: "parent"
},
{
toolTipsTxt: 'xxx新项目原型图设计',
text: '原型图设计',
start_date: '2020-04-08',
id: 21,
duration: 2,
parent: 2,
type: 1,
progress: 0.6,
status: "yellow"
},
{
toolTipsTxt: 'xxx项目-项目设计图',
text: '设计图设计',
start_date: '2020-04-09',
id: 22,
duration: 2,
parent: 2,
type: 2,
progress: 0.6,
status: "pink"
},
{
toolTipsTxt: 'xxx项目-项目确认',
text: '项目确认',
start_date: '2020-04-11',
id: 23,
duration: 2,
parent: 2,
type: 3,
progress: 1,
status: "green"
}
].map(function(current, ind, arry) {
var newObj = {}
if (current.type) { //存在type字段 说明非一级菜单,判断阶段的具体类型 设置不同颜色
if (current.type == 1) { //冒烟
newObj = Object.assign({}, current, {
'color': '#fcca02'
})
} else if (current.type == 2) { //单元
newObj = Object.assign({}, current, {
'color': '#fec0dc'
})
} else if (current.type == 3) { //回归
newObj = Object.assign({}, current, {
'color': '#62ddd4'
})
} else if (current.type == 4) {
newObj = Object.assign({}, current, {
'color': '#d1a6ff'
})
}
} else { //一级菜单是蓝色的
newObj = Object.assign({}, current, {
'color': '#5692f0'
})
}
return newObj
})
},
selectChange(val){
console.log(val)
//测试用例
var obj = {
toolTipsTxt: '新增任务',
text: '新增任务', // 任务名
start_date: '2020-04-15', // 开始时间
id: 24, // 任务id
duration: 2, // 任务时长,从start_date开始计算
parent: 2, // 父任务ID
type: 4,
progress:0,
status: "popular"
}
this.tasks.data.push(obj)
// 数据解析
gantt.parse(this.tasks)
// 刷新数据
gantt.refreshData();
}
},
mounted() {
this.initData()
//自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务
gantt.config.autosize = true
//只读模式
gantt.config.readonly = true
//是否显示左侧树表格
gantt.config.show_grid = true
//表格列设置
gantt.config.columns = [{
name: 'text',
label: '阶段名字',
tree: true,
width: '280',
onrender: function(task, node) {
node.setAttribute("class", "gantt_cell gantt_last_cell gantt_cell_tree " + task.status);
}
},
{
name: 'duration',
label: '时长',
align: 'center',
template: function(obj) {
return obj.duration + '天'
},
hide: true
}
]
var weekScaleTemplate = function(date) {
var dateToStr = gantt.date.date_to_str("%m %d");
var endDate = gantt.date.add(gantt.date.add(date, 1, "week"), -1, "day");
var weekNum = gantt.date.date_to_str("第 %W 周");
return weekNum(date)
};
var daysStyle = function(date) {
var dateToStr = gantt.date.date_to_str("%D");
if (dateToStr(date) == "六" || dateToStr(date) == "日") return "weekend";
return "";
};
gantt.config.subscales = [{
unit: "week",
step: 1,
template: weekScaleTemplate
},
{
unit: "day",
step: 1,
format: "%d"
}
];
gantt.plugins({
tooltip: true
});
gantt.attachEvent("onGanttReady", function() {
var tooltips = gantt.ext.tooltips;
gantt.templates.tooltip_text = function(start, end, task) {
return task.toolTipsTxt + "<br/>" +
"阶段:" + task.text + "<br/>" +
gantt.templates.tooltip_date_format(start)
};
});
//设置任务条进度内容
gantt.templates.progress_text = function(start, end, task) {
return "<div style='text-align:left;color:#fff;padding-left:20px'>" + Math.round(task.progress * 100) +
"% </div>";
};
//任务条显示内容
gantt.templates.task_text = function(start, end, task) {
// return task.text + '(' + task.duration + '天)';
return "<div style='text-align:center;color:#fff'>" + task.text + '(' + task.duration + '天)' +
"</div>";
}
// gantt.templates.scale_cell_class = function(date) {
// /*if(date.getDay()== 0 || date.getDay()== 6){
// return "weekend";
// }*/
// return 'weekend'
// }
//任务栏周末亮色
/*gantt.templates.task_cell_class = function(item,date){
if(date.getDay()== 0 || date.getDay()== 6){
return "weekend";
}
};*/
//任务条上的文字大小 以及取消border自带样式
gantt.templates.task_class = function(start, end, item) {
return item.$level == 0 ? 'firstLevelTask' : 'secondLevelTask'
}
gantt.config.layout = {
css: "gantt_container",
cols: [{
width: 280,
min_width: 280,
rows: [{
view: "grid",
scrollX: "gridScroll",
scrollable: true,
scrollY: "scrollVer"
},
{
view: "scrollbar",
id: "gridScroll",
group: "horizontal"
}
]
},
{
resizer: true,
width: 1
},
{
rows: [{
view: "timeline",
scrollX: "scrollHor",
scrollY: "scrollVer"
},
{
view: "scrollbar",
id: "scrollHor",
group: "horizontal"
}
]
},
{
view: "scrollbar",
id: "scrollVer"
}
]
};
//时间轴图表中,任务条形图的高度
// gantt.config.task_height = 28
//时间轴图表中,甘特图的高度
// gantt.config.row_height = 36
//时间轴图表中,如果不设置,只有行边框,区分上下的任务,设置之后带有列的边框,整个时间轴变成格子状。
gantt.config.show_task_cells = true
//当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度
gantt.config.fit_tasks = true
gantt.config.min_column_width = 50;
gantt.config.auto_types = true;
gantt.config.xml_date = "%Y-%m-%d";
gantt.config.scale_unit = "month";
gantt.config.step = 1;
gantt.config.date_scale = "%Y年%M";
gantt.config.start_on_monday = true;
gantt.config.scale_height = 90;
gantt.config.autoscroll = true;
gantt.config.calendar_property = "start_date";
gantt.config.calendar_property = "end_date";
gantt.config.readonly = true;
gantt.i18n.setLocale('cn');
// 初始化
gantt.init(this.$refs.gantt)
// 数据解析
gantt.parse(this.tasks)
}
}
</script>
<style lang="scss">
.firstLevelTask {
border: none;
.gantt_task_content {
font-size: 13px;
}
}
.secondLevelTask {
border: none;
}
.thirdLevelTask {
border: 2px solid #da645d;
color: #da645d;
background: #da645d;
}
.milestone-default {
border: none;
background: rgba(0, 0, 0, 0.45);
}
.milestone-unfinished {
border: none;
background: #5692f0;
}
.milestone-finished {
border: none;
background: #84bd54;
}
.milestone-canceled {
border: none;
background: #da645d;
}
html,
body {
margin: 0px;
padding: 0px;
height: 100%;
overflow: hidden;
}
.container {
height: 100%;
width: 100%;
position: relative;
.gantt_grid_head_cell {
padding-left: 20px;
text-align: left !important;
font-size: 14px;
color: #333;
}
.select-wrap {
position: absolute;
top: 25px;
z-index: 99;
width: 90px;
left: 180px;
.el-input__inner {
border: none;
}
}
.left-container {
height: 100%;
}
.parent {
.gantt_tree_icon {
&.gantt_folder_open {
background-image: url(assets/gantt-icon.svg) !important;
}
&.gantt_folder_closed{
background-image: url(assets/gantt-icon-up.svg) !important;
}
}
}
.green,
.yellow,
.pink,
.popular {
.gantt_tree_icon.gantt_file {
background: none;
position: relative;
&::before {
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
}
.green {
.gantt_tree_icon.gantt_file {
&::before {
background: #84bd54;
}
}
}
.yellow {
.gantt_tree_icon.gantt_file {
&::before {
background: #fcca02;
}
}
}
.pink {
.gantt_tree_icon.gantt_file {
&::before {
background: #da645d;
}
}
}
.popular {
.gantt_tree_icon.gantt_file {
&::before {
background: #d1a6ff;
}
}
}
}
.left-container {
height: 100%;
}
.gantt_task_content {
text-align: left;
padding-left: 10px;
}
</style>
效果如图:
image.png
获取任务节点
//获取任务节点
gantt.getTask(14) //index: 13 rendered_type: "task" rendered_parent: 1 所有属性
//返回下一个项目的ID(无论嵌套级别是什么:相同或不同)
gantt.getNext( taskId ); //没有就返回null
gantt.getNextSibling(taskId );//没有就返回null
//返回上一个项目的ID:
gantt.getPrev(tsakId)
//返回上一个同级项目的ID:
gantt.getPrevSibling(tsakId)
//返回父任务的ID:
gantt.getParent(tsakId)
//返回任务栏的HTML元素
gantt.getTaskNode('10');//-><div task_id="2" class="gantt_task_line" …>…</div>
gantt.getTaskRowNode('10');//-><div class="gantt_row" task_id="2">…</div>
//根据指定条件查找任务
var userTasks = gantt.getTaskBy("user_id", 5);
var userTasks2 = gantt.getTaskBy(function(task){
return task.user_id == 5 || !task.user_id;
});
var userTasks = gantt.getTaskBy(task => task.user_id == 5);
//通过其全局任务索引返回任务
var globalTaskIndex = gantt.getGlobalTaskIndex(19); // -> 10 var task = gantt.getTaskByIndex(10);
//返回指定时间段内发生的任务的集合
var tasks = gantt.getTaskByTime(new Date(2013,3,10),new Date(2013,4,10));
for (var i=0; i<tasks.length; i++){
alert(tasks[i].text);
}
var tasks = gantt.getTaskByTime();//returns all tasks
//返回指定父分支的第一级子任务
gantt.getChildren( taskId)
//返回指定任务的兄弟姐妹(包括自身)
gantt.getSiblings("t_1"); -> //["t_1", "t_2]
// 检查当前是否选择了指定的任务
gantt.isSelectedTask(task.id)
// 检查指定任务是否存在
gantt.isTaskExists(10); // ->true
// 检查指定任务是否当前在甘特图中呈现
gantt.isTaskVisible("t_1"); // ->true
// 返回配置
gantt.getScale() //返回事件的配置事件头单元格宽度70高度12,总的宽度5600。列数80,每格的做边距0,70,140……;单位day
// 获取甘特图中当前加载的任务数
gantt.getTaskCount();
// 获取分支中任务的索引
var taskIndex = gantt.getTaskIndex("t_1"); // -> 0
var globalTaskIndex = gantt.getGlobalTaskIndex("t_1"); // -> 1
//返回任务的类型
var type = gantt.getTaskType(gantt.getTask(12));
//通过左边表格里列的名称返回列的索引
var index = gantt.getColumnIndex("start_date"); // => 1
//根据 taskId 返回所有相关任务以及相关的链接
gantt.getConnectedGroup(18);
//获取所有的ID
gantt.getDatastore("task").fullOrder
//获取所有节点
gantt.getDatastore("task").pull
//返回日期的列索引columnIndexByDate
gantt.columnIndexByDate(new Date(2017, 03, 11)); // ->10
//返回所选任务的ID:
gantt.getSelectedId()
//返回当前选定任务的数组:
gantt.getSelectedTasks();//getLastSelectedTask; isSelectedTask
//检查指定项目是否具有子任务:
gantt.hasChild("p_1"); //-> true
// 获取屏幕上可见的任务数(未折叠的任务):
gantt.getVisibleTaskCount();
位置相关可能用到API
//返回任务的可见高度
var height = gantt.getTaskHeight(); // -> 30
//任务的DOM元素在时间轴区域中的位置和大小
var sizes = gantt.getTaskPosition(task, task.planned_start, task.planned_end); //=>left,top,height,width
//获取任务的DOM元素在时间轴区域中的最高位置
gantt.getTaskTop('10');
//获取指定日期在图表区域中的相对水平位置 gantt.posFromDate(new Date(2013,02,31)); // -> 0
gantt.posFromDate(new Date(2013,03,1)); // -> 74
gantt.posFromDate(new Date(2013,03,2)); // -> 148
//滚动图表区域以使指定的日期可见
gantt.showDate(new Date()); //shows the current date
// 在甘特图中启用/禁用多任务选择:
gantt.config.multiselect = false;
// 指定在一个或任何级别内是否可以使用多任务选择:
gantt.config.multiselect_one_level = true;
//甘特图任务悬浮框位置
gantt.config.tooltip_offset_x = 10;
gantt.config.tooltip_offset_y = 30;
//激活列表展开(折叠)功能
gantt.config.open_split_tasks = true;
//甘特图图表宽度自适应
gantt.config.autofit = true;
//用户可以通过拖拽调整行高
gantt.config.resize_rows = true;
//界面初始化时展开图表树形结构
gantt.config.open_tree_initially = true;
//默认滚动到当前时间
gantt.showDate(new Date()); //shows the current date
//使指定的任务在屏幕上可见
gantt.showTask('10');
//设置甘特图表头高度
gantt.config.scale_height = 50;
//设置行高
gantt.config.row_height = 44;
//配置甘特图时间刻度高度
gantt.config.scale_height = 40;
//跳转定位
let colIndex = simulationGantt.columnIndexByDate(new Date( task.start_date ));
simulationGantt.scrollTo( (colIndex-5)*col_width, (task.$index-2)*34);
//滚动到位置 scrollTo
//返回滚动位置
var sPos = gantt.getScrollState(); // {x:58,y:180}
var posX = sPos.x; var posY = sPos.y;
//当甘特图滚动到特定点时触发onGanttScroll(数左,数顶部){...} gantt.attachEvent("onGanttScroll", function (left, top){
// any custom logic here
})
//获取图表区域中指定水平位置的日期//参数相当于列的index
gantt.dateFromPos(0);//返回第0列的日期
消息弹框API
//消息框
gantt.message({
type:"confirm-warning",
text:"Are you sure you want to do it?",
expire: 1000,//过期时间
});
//模态框
gantt.modalbox({
title: "Close",
type: "alert-warning"
});
//屏幕右上角的红色弹出窗口显示(第一个参数必为false)
gantt.assert( false, task.text);
//调用确认消息框
gantt.confirm({
text: "Continue?",
ok:"Yes", cancel:"No",
callback: function(result){
if(result){
gantt.message("Yes!");
}else{
gantt.message("No...");
}
}
});
//警报框的配置
gantt.alert({ //confirm,message,modalbox
title:"Alert",
type:"alert-error",
text:"You can't do this"
});
gantt.assert( false, task.text);
标记标签
//在灯箱区域添加标记
gantt.plugins({ marker: true });
gantt.config.task_date = "%Y-%m-%d";
var dateToStr = gantt.date.date_to_str(gantt.config.task_date);
var todayMarker = null;
var startTime = new Date("2020-12-13");
todayMarker = gantt.addMarker({
start_date: startTime,
end_date: simulationGantt.calculateEndDate(new Date("2020-12-13"), task.duration),
css: "gantt-start-line",
text: "开始时间",
});
//删除灯箱区域添加标记
gantt.deleteMarker(todayMarker);
<style>
.gantt-end-line{ background-color: #ffeb3b; color: #fff; }
.gantt-start-line { background-color: #0ca30a; color: #fff; }
</style>
事件
// 选择指定的任务、从所选任务中删除选择
gantt.selectTask("t_1"); gantt.unselectTask();
// 在网格中排序任务:
gantt.sort("text",true);//排序的列的名称/true-降序排序,false-升序排序。默认情况下为false
// 将任务移到新位置
gantt.moveTask("t_1", 1);
// 打开具有指定ID的分支
gantt.open("p_1");
// 激活指定的插件
gantt.plugins({
quick_info: true,
keyboard_navigation: true,
// multiselect: true,// 激活多任务选择
});
// 更新指定的任务
var taskId = gantt.addTask({
id:10,
text:"Task #10",
start_date:"02-04-2013",
duration:8,
});
gantt.getTask(taskId).text = "Task #13"; //changes task's
data gantt.updateTask(taskId); //renders the updated task
//初始化promise的回调
gantt.Promise(function(resolve, reject) {
setTimeout(function(){ resolve(); }, 5000);
}).then(function(){ alert("Resolved") });
//添加链接
var linkId = gantt.addLink({ id:1, source:1, target:2, type:gantt.config.links.finish_to_start });
//绑定事件【attachEvent(GanttEventName名称,函数处理程序,对象设置);对象设置可以没有】
var myEvent = gantt.attachEvent("onTaskClick", function(id, e) {
alert("You've just clicked an item with id="+id);
}, {id: "my-click", once: true }); //可以指定id,是否只执行一次
//取消绑定的事件
gantt.detachEvent("my-click");
gantt.detachEvent(myEvent);
// 是指定任务不触发内部事件或服务器端调用:silent
//双击任务触发(每一行)
gantt.attachEvent("onTaskDblClick", function (id, e) {return true})
//将任务添加到Gantt之前触发
gantt.attachEvent("onAfterTaskAdd",function(id,item){return true})
//用户选择任务时触发
gantt.attachEvent("onTaskSelected",function(id){return true})
//用户悬停Gantt时触发
gantt.attachEvent("onMouseMove",function(id,e){})
//用户拖拽任务后释放鼠标之后,应用更改之前触发
gantt.attachEvent("onAfterTaskDrag",function(id,mode,e){return true})
//点击“+”进行添加任务操作触发
gantt.attachEvent("onTaskCreated",function(task){return true})
//用户打开Gantt内置弹出框之前触发
gantt.attachEvent("onBeforeLightbox",function(id){return true})
//自动排程:需要插件auto_scheduling插件。
gantt.autoSchedule();
//要从特定任务开始重新计算计划,请将任务的id作为参数传递给autoSchedule()方法
gantt.autoSchedule(taskId);
//全屏
gantt.expand();//全屏
gantt.collapse();//退出全屏
//计算完成任务的日期
gantt.calculateEndDate({start_date: new Date(2013,02,15), duration: 48});
gantt.calculateEndDate(new Date(2013,02,15), 48);
//判断是否存在参数,则返回false;否则返回true
if(gantt.defined(task.custom_property)){
// ..
}
//销毁甘特图实
var myGantt = Gantt.getGanttInstance(); myGantt.destructor();
//隐藏灯箱模式叠加层,以阻止与其余屏幕的交互
gantt.hideCover(gantt.getLightbox());
//如果灯箱当前处于活动状态,则将其关闭
gantt.showLightbox(1); gantt.hideLightbox()
遍历节点
//遍历甘特图中指定任务的所有父任务
gantt.eachParent(function(task){
alert(task.text);
}, taskId);
//遍历甘特图中的所有选定任务 eachSelectedTask
//遍历特定任务或整个甘特图的所有子任务 eachTask
//遍历被选中的节点 eachSelectedTask
导入导出
exportToExcel、exportToMSProject、exportToICal、exportToPDF、exportToPNG、exportToJSON
importFromMSProject
参考链接
插件文档地址:https://docs.dhtmlx.com/gantt/api__refs__gantt.html
https://blog.csdn.net/qq_24641385/article/details/112464817
https://www.cnblogs.com/zyfenblog/p/15608310.html
网友评论