使用的插件:dhtmlx-gantt
下载方式:npm i dhtmlx-gantt
插件官网:Gantt API Gantt Docs (dhtmlx.com)
作品展示
直接上全部代码
<template>
<div class="card">
<el-card>
<div class="ard">
<el-radio-group v-model="radio2">
<el-radio-button label="全部" />
<el-radio-button label="进行中" />
<el-radio-button label="已超时" />
<el-radio-button label="已完成" />
</el-radio-group>
<div class="asd">
<p>开始时间:</p>
<el-date-picker v-model="value1" type="date" placeholder="点击选择时间" :size="size" />
</div>
<div class="asd">
<p>结束时间:</p>
<el-date-picker v-model="value1" type="date" placeholder="点击选择时间" :size="size" />
</div>
<div class="asd">
<p>选择任务类型:</p>
<el-select v-model="value" class="m-2" placeholder="下拉选择" style="width: 170px">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<el-button style="margin-left: 10px;" type="primary" :icon="Filter">筛选</el-button>
<el-button type="primary" :icon="Plus">新增</el-button>
</div>
</el-card>
<el-card class="box-card">
<div class="cardtop">
<div class="margins">
<p><el-color-picker v-model="objs.asd1" show-alpha />攻击组</p>
<p><el-color-picker v-model="objs.asd2" show-alpha />防御组</p>
<p><el-color-picker v-model="objs.asd3" show-alpha />目标组</p>
</div>
<el-radio-group v-model="radio1" size="small">
<el-radio-button label="年" />
<el-radio-button label="月" />
<el-radio-button label="日" />
</el-radio-group>
</div>
<div id="gantt_here" style="margin-top: 10px;" class="gantt-container"></div>
</el-card>
</div>
</template>
<script setup>
import { reactive, toRefs, ref, onBeforeMount, onMounted, watchEffect, defineExpose } from 'vue'
import { gantt } from 'dhtmlx-gantt'
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
import { Plus, Filter } from '@element-plus/icons-vue'
const data = reactive({})
const radio1 = ref('年')
const radio2 = ref('全部')
const value1 = ref('')
const value = ref('')
let objs = reactive({
asd1: '#f2e6c2',
asd2: '#b5e09b',
asd3: '#baefe2'
})
let dialogVisible = ref(false)
//初始化甘特图
const initGantt = () => {
var tasks = {
data: [
{
id: 1,
taskname: '明天吃烩菜',
parent: 0,
start_date: "01-04-2018",
progress: 0.3,
duration: 1,
types: 1,
text: '李大厨',
color: objs.asd1,
tsakrank: 0,
},
{
id: 2,
taskname: '明天吃鱼肉',
parent: 0,
start_date: "01-04-2018",
progress: 0.42,
duration: 5,
types: 2,
color: objs.asd2,
text: '王大厨',
tsakrank: 1,
},
{
id: 3,
taskname: '明天吃西餐',
parent: 0,
start_date: "01-04-2018",
progress: 0.65,
duration: 5,
types: 3,
text: '赵大厨',
color: objs.asd3,
tsakrank: 2,
},
{
id: 4,
taskname: '购买水军发动舆论偏差',
parent: 1,
start_date: "01-04-2018",
progress: 0.1,
duration: 1,
types: 1,
text: '李大厨',
color: objs.asd1
},
{
id: 5,
taskname: '编辑一边有效证据的文章',
parent: 2,
start_date: "01-04-2018",
progress: 0.1,
duration: 3,
types: 2,
text: '王大厨',
color: objs.asd2
},
{
id: 6,
taskname: '寻找目标人物关键证据',
parent: 3,
start_date: "01-04-2018",
progress: 0.1,
duration: 3,
types: 3,
text: '赵大厨',
color: objs.asd3
},
{
id: 7,
taskname: '发布目标任务黑料',
parent: 1,
start_date: "03-04-2018",
progress: 0.2,
duration: 2,
types: 1,
text: '李大厨',
color: objs.asd1
},
{
id: 8,
taskname: '打造慈善公益效果',
parent: 2,
start_date: "04-04-2018",
progress: 0.1,
duration: 3,
types: 2,
text: '王大厨',
color: objs.asd2
},
{
id: 9,
taskname: '查看目标亲朋好友博客',
parent: 3,
start_date: "02-04-2018",
progress: 0.1,
duration: 6,
types: 3,
text: '赵大厨',
color: objs.asd3
},
],
// links: [
// { id: 1, source: 1, target: 2, type: "1" },
// { id: 2, source: 2, target: 3, type: "0" },
// { id: 3, source: 3, target: 4, type: "1" },
// { id: 4, source: 4, target: 5, type: "0" },
// ]
};
gantt.config.grid_width = 350
gantt.config.add_column = false //添加符号
gantt.config.autosize = true//自适应尺寸
gantt.config.autofit = true// 表格列宽自适应
gantt.config.autoscroll = true// 把任务或者连线拖拽到浏览器屏幕外时,自动触发滚动效果
gantt.config.drag_progress = false//取消任务进度条进度拖动
gantt.config.scale_height = 60
gantt.config.row_height = 60
gantt.config.bar_height = 34
gantt.config.fit_tasks = true //自动延长时间刻度,以适应所有显示的任务
gantt.config.auto_types = true //将包含子任务的任务转换为项目,将没有子任务的项目转换回任务
gantt.i18n.setLocale('cn') //设置语言
//时间栏配置
gantt.config.scales = [
{ unit: 'month', step: 1, format: '%Y年%m月' },
{ unit: 'day', step: 1, format: '%m/%d' },
]
//左侧列表配置
gantt.config.columns = [
{ name: "taskname", label: "任务名称", align: 'left', tree: true, width: 140 },
{
name: "progress", label: "任务优先", align: 'center', width: 80, template: function (task) {
let obj = {
color: task.tsakrank === 0 ? '#ff2b00' : task.tsakrank === 1 ? '#ffab00' : '#409eff',
icon: task.tsakrank === 0 ? 'icon-youxianjiP0' : task.tsakrank === 1 ? 'icon-youxianjiP1' : 'icon-youxianjiP2',
}
return `<div class="jindu" style="color:${obj.color};"><i style="font-size:24px;" class="iconfont ${obj.icon}"></i></div>`
}
},
{
name: "type", label: "任务类别", align: 'center', width: 100, template: function (task) {
let obj = {
color: task.types === 1 ? '#f29d38' : task.types === 2 ? '#65c16f' : '#1890ff',
icon: task.types === 1 ? 'icon-gongji' : task.types === 2 ? 'icon-kaiqifangyu' : 'icon-icon--mubiaoku',
text: task.types === 1 ? '攻击' : task.types === 2 ? '防御' : '目标'
}
return `<div class="tasktype" style="color:${obj.color};font-size:14px;">
<i class="iconfont ${obj.icon}"></i>
<span style="margin-left:3px;"> ${obj.text}</span>
</div>`
}
},
{
name: "progress", label: "任务进度", align: 'center', width: 80, template: function (task) {
return `<div class="jindu" style="width:100%;height:30px;padding-left:10px;font-size:13px;color:black;"><span>${(task.progress * 100).toFixed(0) + "%"}</span></div>`;
}
},
]
//鼠标移入弹框
// gantt.templates.tooltip_text = function (start, end, task) {
// return `
// <div style="width: 200px;height: 200px;">
// <p>任务名称:这是一个任务</p>
// <p>任务策划:张三</p>
// <p>当前状态:进行中</p>
// <p>任务类别:攻击</p>
// <p>开始时间:2020-12-11</p>
// <p>结束时间:2021-04-13</p>
// </div>
// `
// };
//更改父项图标
gantt.templates.grid_folder = (item) => {
return ""
}
gantt.plugins({
marker: true
});
var date_to_str = gantt.date.date_to_str(gantt.config.task_date);
var today = new Date();
gantt.addMarker({
start_date: today,
css: "today",
text: "今天",
title: "今天: " + date_to_str(today)
});
//更改子项图标
gantt.templates.grid_file = (item) => {
return ""
}
//任务条显示内容
gantt.templates.task_text = function (start, end, task) {
return `
<div style="color:#454545;font-size:14px;font-weight:700;">执行:${task.text}</div>
`
}
//任务条左侧配置
// gantt.templates.leftside_text = function (start, end, task) {
// return `<div class="jindu" style="width:100%;height:30px;background-color:#e6f4ff;padding-left:10px;font-size:13px;color:#629eff;"><span>当前进度${(task.progress * 100).toFixed(0) + "%"}</span></div>`;
// };
//展开树图标
gantt.templates.grid_open = function (item) {
return `<i style="font-size:14px;background:none; color:#1890ff; padding-left:10px;" class="gantt_tree_icon gantt_${item.$open ? "close" : "open"} iconfont ${item.$open ? 'icon-zhankaishousuo' : 'icon-zhankaishousuo1'}"></i>`
};
gantt.init('gantt_here') //初始化
gantt.parse(tasks) //填充数据
//双击事件
gantt.attachEvent("onTaskDblClick", function (id, e) {
// 在这里编写处理双击事件的代码
console.log("双击了任务:" + id);
dialogVisible.value = true
});
}
onBeforeMount(() => { })
onMounted(() => {
initGantt()
})
watchEffect(() => { })
defineExpose({
...toRefs(data)
})
</script>
<style scoped lang="scss">
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background-color: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background-color: #888;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background-color: #555;
}
.renwus {
width: 100%;
height: 200px;
display: flex;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
overflow: auto;
}
.renwu {
width: 100%;
height: 200px;
display: flex;
align-items: center;
justify-content: space-around;
flex-wrap: wrap;
}
:deep(.el-progress-circle) {
width: 100px !important;
height: 80px !important;
}
.ps {
padding: 0;
margin: 0;
}
.percentage-value {
display: block;
margin-top: 10px;
font-size: 28px;
}
.percentage-label {
display: block;
margin-top: 10px;
font-size: 12px;
}
.demo-progress .el-progress--line {
margin-bottom: 15px;
width: 350px;
}
.demo-progress .el-progress--circle {
margin-right: 15px;
}
.cardtop {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.margins {
display: flex;
font-size: 12px;
p {
margin-left: 10px;
:deep(.el-color-picker .el-color-picker__icon) {
opacity: 0;
}
:deep(.el-color-picker__trigger) {
border: none;
width: 25px;
height: 25px;
}
}
}
}
.box-card {
margin-top: 20px;
}
.card {
width: 1500px;
height: 1000px;
margin: 0 auto;
.ard {
width: 100%;
height: 40px;
display: flex;
align-items: center;
}
.icons {
width: 80px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #a0cfff;
color: #46a2ff;
margin-right: 10px;
border-radius: 7px;
background-color: #ecf5ff;
i {
color: #1890ff;
font-size: 14px;
margin-right: 5px;
}
}
}
.asd {
width: 300px;
height: 33px;
border-radius: 5px;
border: 1px dotted #ccc;
margin-left: 20px;
display: flex;
align-items: center;
p {
color: #606266;
margin-left: 5px;
}
:deep(.el-input__wrapper) {
border: none;
box-shadow: none !important;
}
:deep(.el-date-editor.el-input) {
width: 200px !important;
}
:deep(.el-select__wrapper) {
border: none;
box-shadow: none !important;
}
}
:deep(.gantt_layout_cell) {
border-radius: 7px;
}
:deep(.gantt_tree_indent) {
opacity: 0;
}
:deep(.gantt_grid_scale .gantt_grid_head_cell) {
color: #606266;
font-size: 15px;
font-weight: 700;
border-right: 1px solid #ccc !important;
}
:deep(.gantt_scale_cell) {
color: #454545 !important;
}
:deep(.gantt_grid_data .gantt_cell) {
border-right: 1px solid #ccc !important;
padding: 0;
}
:deep(.gantt_task_progress_wrapper) {
border-radius: 5px;
}
:deep(.gantt_task_line.gantt_project) {
border-radius: 5px;
border: none;
}
:deep(.gantt_data_area div) {
border-radius: 5px;
// border:none;
}
:deep(.gantt_tree_content) {
display: flex;
align-items: center;
.jindu {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
color: #4482e3;
border-radius: 10px;
}
.tasktype {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
:deep(.gantt_task_line) {
border: none;
}
:deep(.gantt_link_point) {
display: none !important;
}
:deep(.gantt_task_progress) {
height: 100%;
}
.toppingTask {
width: 200px;
height: 200px;
background-color: #1890ff;
}
</style>
不懂的直接区官网查看就好 什么api都有