- 安装 dhtmlx-gantt 我用的版本是 8.0.1
yarn add dhtmlx-gantt --save
或者
npm install dhtmlx-gantt --save - 效果图
- 直接贴代码可以使用 加了一个延迟两秒的定时器,是为了防止某种(俺也不知道)情况下报错
<template>
<div>
<div>
展示方式: <el-select @change="aSelectChange" v-model="selectValue">
<el-option label="1小时" value="1小时"></el-option>
<el-option label="3小时" value="3小时"></el-option>
<el-option label="1天" value="1天"></el-option>
</el-select>
</div>
<!-- 甘特图 -->
<div ref="ganttRef"></div>
<!-- 弹窗 -->
<el-dialog :append-to-body="true" :close-on-click-modal="false" :visible.sync="dialogAddVisible" width="800px"
@close="closing">
<span slot="title">{{ title }}</span>
<div>
测试消息
</div>
</el-dialog>
</div>
</template>
<script>
import { gantt } from 'dhtmlx-gantt';
import "dhtmlx-gantt/codebase/dhtmlxgantt.css";
export default {
data() {
return {
dialogAddVisible: false,
title: "",
selectValue: "1天",
ganttList: { data: [], links: [] },
ganttColumns: [
// tree: true, width: "*", min_width: 120,
{
align: 'left', name: 'text', tree: true, label: '列表',
template: function (task) {
return "<div class='tttttt'>" + `${task.render == "split22" ? task.ceshi1 : task.text}` + "</div>"
}
},
{
align: 'center', name: 'ceshi7', label: '完成率(%)',
template: function (task) {
return "<div class='tttttt'>" + `${task.render == "split22" ? '' : Math.floor((task.ceshi7 / task.ceshi6) * 100)}` + "</div>"
}
},
],
};
},
beforeDestroy() {
//
gantt.detachEvent("onTaskClick");
gantt.clearAll();
},
mounted() {
let that = this;
//任务的点击方法
gantt.attachEvent("onTaskClick", (id, e) => {
const task = gantt.getTask(id);
if (task.$level === 0) {
// 如果该任务是一个父任务,则不触发展开事件
return true;
} else {
// 如果该任务是一个子任务或孙子任务,则触发展开事件
that.showChart(id);
return true;
}
});
},
created() {
gantt.clearAll();
this.search();
},
methods: {
async showChart(id) {
let that = this;
// 弹窗信息
that.dialogAddVisible = true;
that.title = "弹窗信息";
},
async search() {
let that = this;
const data=[{
"ceshi1": "06032308240004",
"ceshi2": "401",
"ceshi3": "测试1",
"ceshi4": "2023-07-24 14:53:39",
"ceshi5": "2023-07-28 14:53:39",
"ceshi6": 1002,
"ceshi7": 600
},{
"ceshi1": "06032308240004",
"ceshi2": "401",
"ceshi3": "测试2",
"ceshi4": "2023-07-28 14:53:39",
"ceshi5": "2023-07-29 14:53:39",
"ceshi6": 1002,
"ceshi7": 600
},{
"ceshi1": "06022307260001",
"ceshi2": "A003",
"ceshi3": "测试2",
"ceshi4": "2023-07-26 13:33:05",
"ceshi5": "2023-07-27 13:33:06",
"ceshi6": 9500,
"ceshi7": 5000
}]
let param = data.map((item, index) => {
return {
id: index + 1,
text: item.ceshi3,
progress: Math.round(item.ceshi7 / item.ceshi6) * 100,
start_date: new Date(item.ceshi4),
end_date: new Date(item.ceshi5),
color: '#e1f3d8',
...item
}
})
// 创建一个对象,用于存储分类后的数据
let classifiedData = {};
// 遍历原始数据数组
for (const item of param) {
const { id, ceshi1 } = item;
// 如果分类对象中不存在该分类,则创建一个新的数组
if (!classifiedData[ceshi1]) {
classifiedData[ceshi1] = [];
}
// 将数据项添加到对应分类的数组中
classifiedData[ceshi1].push(item);
}
// 遍历分类后的数据
for (const category in classifiedData) {
const categoryData = classifiedData[category];
// 复制分类的第一个数据项
const firstItemCopy = { ...categoryData[0] };
firstItemCopy.id = param.length + firstItemCopy.id
// 将复制的数据项添加到分类数组的开头
categoryData.splice(1, 0, firstItemCopy);
// 给分类的第一个数据项添加render属性
const firstItem = categoryData[0];
firstItem.render = "split22";
firstItem.open = true;
// 给剩余数据项添加parent属性,值为分类的第一个id
for (let i = 1; i < categoryData.length; i++) {
categoryData[i].parent = firstItem.id;
}
}
// 这里是为了 重新组装一下
let param3 = [];
Object.keys(classifiedData).map(item => {
classifiedData[item].forEach(el => {
param3.push(el)
});
})
setTimeout(() => {
this.ganttList.data = param3 || [];
gantt.config.columns = this.ganttColumns;
gantt.templates.task_class = function (start, end, task) {
// console.log(task)
// 如果是父级的话,不显示进度块
switch (task.parent) {
case 0:
return "low";
break;
default:
return "high";
break;
}
};
gantt.templates.progress_text = function (start, end, task) {
return Math.round((task.ceshi7 / task.ceshi6) * 100) + "%"
}
gantt.clearAll();
gantt.plugins({
auto_scheduling: true
});
gantt.config.order_branch = true;
gantt.config.order_branch_free = true;
gantt.config.auto_types = true;
gantt.config.auto_scheduling = true;
gantt.config.auto_scheduling_compatibility = true;
gantt.locale.labels.section_split = "Display";
gantt.i18n.setLocale('cn'); // 设置中文
gantt.config.work_time = true;
gantt.config.readonly = true; // 设置为只读
gantt.config.bar_height = 24; //task高度
//自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务
gantt.config.autosize = true;
gantt.config.show_progress = true;
gantt.config.columns = this.ganttColumns;
gantt.config.scales = [
{ unit: 'month', step: 1, format: '%F %Y' },
{ unit: "day", step: 1, format: "%d" },
// { unit: 'day', step: 1, format: '%Y %F %d' },
// { unit: "day", step: 1, format: "%d" },
// { unit: "hour", step: 3, format: "%H:%i" }
// { unit: 'week', step: 1, format: weekScaleTemplate },
];
// gantt.config.start_date = "0";
// setTimeout(() => {
gantt.init(this.$refs.ganttRef);
gantt.parse(this.ganttList);
// }, 1000)
}, 2000)
},
aSelectChange(value) {
if (value == "1小时") {
gantt.config.scales = [
{ unit: 'month', step: 1, format: '%F %Y %d' },
{ unit: "hour", step: 1, format: "%H:%i" }
// { unit: 'week', step: 1, format: weekScaleTemplate },
];
} else if (value == "3小时") {
gantt.config.scales = [
{ unit: 'month', step: 1, format: '%F %Y' },
{ unit: "day", step: 1, format: "%d" },
{ unit: "hour", step: 3, format: "%H:%i" }
// { unit: 'week', step: 1, format: weekScaleTemplate },
];
} else {
gantt.config.scales = [
{ unit: 'month', step: 1, format: '%F %Y' },
{ unit: "day", step: 1, format: "%d" },
// { unit: "hour", step: 3, format: "%H:%i" }
// { unit: 'week', step: 1, format: weekScaleTemplate },
];
}
gantt.init(this.$refs.ganttRef);
},
closing() {
this.dialogAddVisible = false;
},
cancel() {
this.closing();
},
submit() {
this.closing();
},
},
};
</script>
<style lang="scss" >
.high .gantt_task_progress {
background: #67C23A !important;
opacity: 1 !important;
}
.gantt_task_content {
opacity: 0 !important;
}
.low {
display: none !important;
}
.complex_gantt_bar {
background: transparent !important;
border: none !important;
}
.complex_gantt_bar .gantt_task_progress {
display: none !important;
}
.publicAfter::after {
content: "";
width: 20px;
height: 10px;
border-radius: 5px;
display: inline-block;
}
.planProduct::after {
background: rgb(225, 243, 216);
}
.realityProduct::after {
background: #67C23A;
}
.planHalt::after {
background: rgb(253, 226, 226);
}
.realityHalt::after {
background: rgb(245, 108, 108);
}
</style>
4:更多 可看官方例子,里面有代码
Gantt : Samples