首页 前端知识 超多功能的免费甘特图 适用(vue)

超多功能的免费甘特图 适用(vue)

2024-04-22 09:04:28 前端知识 前端哥 274 389 我要收藏

使用的插件: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都有

转载请注明出处或者链接地址:https://www.qianduange.cn//article/5693.html
标签
甘特图
评论
会员中心 联系我 留言建议 回顶部
复制成功!