vue+dhtmlx-gantt 实现甘特图-快速入门【甘特图】
文章目录
- 一、前言
- 二、使用说明
- 2.1 引入依赖
- 2.2 引入组件
- 2.3 引入dhtmlx-gantt
- 2.4 甘特图数据配置
- 2.5 初始化配置
- 三、代码示例
- 3.1 Vue2完整示例
- 3.2 Vue3 完整示例
- 四、效果图
一、前言
dhtmlxGantt 是一款功能强大的甘特图组件,支持 Vue 3 集成。它提供了丰富的功能,适合复杂的项目管理需求。

特点
- 支持拖放操作
- 多种视图模式(天、周、月、年)
- 数据导出功能(PDF、PNG、Excel)
- 任务依赖关系管理
使用场景
适合需要高度定制化和复杂功能的企业级项目管理工具。
资源
- GitHub: dhtmlxGantt
- 文档: dhtmlxGantt 文档
二、使用说明
2.1 引入依赖
npm install dhtmlx-gantt
2.2 引入组件
<template><div><div ref="gantt" style="height:500px;" /></div>
</template>
2.3 引入dhtmlx-gantt
import gantt from 'dhtmlx-gantt'
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
2.4 甘特图数据配置
- 父级时间是根据子级
start_date以及duration自动计算 progress:完成度的最大值为1open:是否展开文件parent:父级idstart_date:开始时间(日月年)text:左边数据展示文件名称(可以自定义添加展示字段,在后面列配置项可以配置)
📢注意: 数据格式类似于树形组件,子级需要父级的
id
tasks: {data: [// {// id: 11,// text: 'Project #1',// // type: gantt.config.types.project,// progress: 0.5,//完成度// open: true,//默认打开// number: '20240227',//显示字段// },// {// toolTipsTxt: '任务#101-001',// id: 12,//任务id// text: '任务#1',//任务名称// start_date: '03-04-2022',//开始时间 日月年// duration: '5',//任务时常// parent: '11',//父级id// progress: 1,//完成度// open: true,//默认打开// },// {// id: 13,// text: '任务#2',// start_date: '03-04-2022',// // type: gantt.config.types.project,// parent: '11',// progress: 0.255,// open: true,// },// {// id: 14,// text: '任务#3',// start_date: '01-04-2022',// duration: '6',// parent: '11',// progress: 0.8,// open: true,// },// {// id: 15,// text: '任务#4',// // type: gantt.config.types.project,// parent: '11',// progress: 0.2,// open: true,// },// {// id: 16,// text: 'Final milestone',// start_date: '15-04-2022',// // type: gantt.config.types.milestone,// parent: '11',// progress: 0,// open: true,// },// {// id: 17,// text: '任务#2.1',// start_date: '03-04-2022',// duration: '2',// parent: '13',// progress: 1,// open: true,// },// {// id: 18,// text: '任务#2.2',// start_date: '06-04-2022',// duration: '3',// parent: '13',// progress: 0.8,// open: true,// },// {// id: 19,// text: '任务#2.3',// start_date: '10-04-2022',// duration: '4',// parent: '13',// progress: 0.2,// open: true,// },// {// id: 20,// text: '任务#2.4',// start_date: '10-04-2022',// duration: '4',// parent: '13',// progress: 0,// open: true,// },// {// id: 21,// text: '任务#4.1',// start_date: '03-04-2022',// duration: '4',// parent: '15',// progress: 0.5,// open: true,// },// {// id: 22,// text: '任务#4.2',// start_date: '03-04-2022',// duration: '4',// parent: '15',// progress: 0.1,// open: true,// },// {// id: 23,// text: 'Mediate milestone',// start_date: '14-04-2022',// // type: gantt.config.types.milestone,// parent: '15',// progress: 0,// open: true,// },],
tasks 中 link 连线配置
tasks: {// #字段解释// 格式 id:数据id // source:开始链接的项目id ----为tasks.data中数据的id// target:要链接项目的id ----为tasks.data中数据的id// type: 0--进行-开始 `尾部链接头部` // 1--开始-开始 `头部链接头部`// 2--进行-进行 `尾部链接尾部`// 3--开始-进行 `头部链接尾部`// 任务之间连接links: [{ id: '10', source: '11', target: '12', type: '1' },{ id: '11', source: '11', target: '13', type: '1' },{ id: '12', source: '11', target: '14', type: '1' },{ id: '13', source: '11', target: '15', type: '1' },{ id: '14', source: '23', target: '16', type: '0' },{ id: '15', source: '13', target: '17', type: '1' },{ id: '16', source: '17', target: '18', type: '0' },{ id: '17', source: '18', target: '19', type: '0' },{ id: '18', source: '19', target: '20', type: '0' },{ id: '19', source: '15', target: '21', type: '2' },{ id: '20', source: '15', target: '22', type: '2' },{ id: '21', source: '15', target: '23', type: '0' },],},
2.5 初始化配置
弹窗汉化
gantt.locale.labels = {dhx_cal_today_button: "今天",day_tab: "日",week_tab: "周",month_tab: "月",new_event: "新建日程",icon_save: "保存",icon_cancel: "关闭",icon_details: "详细",icon_edit: "编辑",icon_delete: "删除",confirm_closing: "请确认是否撤销修改!", //Your changes will be lost, are your sure?confirm_deleting: "是否删除计划?",section_description: "描述:",section_time: "时间范围:",section_type: "类型:",section_text: "计划名称:",section_test: "测试:",section_projectClass: "项目类型:",taskProjectType_0: "项目任务",taskProjectType_1: "普通任务",section_head: "负责人:",section_priority: '优先级:',taskProgress: '任务状态',taskProgress_0: "未开始",taskProgress_1: "进行中",taskProgress_2: "已完成",taskProgress_3: "已延期",taskProgress_4: "搁置中",section_template: 'Details',/* grid columns */column_text: "计划名称",column_start_date: "开始时间",column_duration: "持续时间",column_add: "",column_priority: "难度",/* link confirmation */link: "关联",confirm_link_deleting: "将被删除",message_ok: '确定',message_cancel: '取消',link_start: " (开始)",link_end: " (结束)",type_task: "任务",type_project: "项目",type_milestone: "里程碑",minutes: "分钟",hours: "小时",days: "天",weeks: "周",months: "月",years: "年"}

清空旧数据
gantt.clearAll(); // 清空旧数据
📢注意:其中值得一提的就是更新数据,需要清空旧数
初始化数据
// 初始化init() {// 格式化日期gantt.locale.date = {month_full: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],day_full: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],day_short: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]}console.log(gantt);//自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务gantt.config.autosize = true//只读模式gantt.config.readonly = false//是否显示左侧树表格gantt.config.show_grid = true// //表格列设置gantt.config.columns = [{ name: 'text', label: '阶段名字', tree: true, width: '150', align: 'center', },// { name: 'number', label: '工单号', tree: false, width: '120', align: 'center', },{name: 'duration',label: '工时',align: 'center',template: function (obj) {return obj.duration + '天'},},/*{name:"start_date", label:"开始时间", align: "center" },{name:"end_date", label:"结束时间", align: "center" },*/]// 自动延长时间刻度gantt.config.fit_tasks = true// 允许拖放gantt.config.drag_project = true// 定义时间格式gantt.config.scales = [{ unit: 'month', step: 1, date: ' %Y,%F' },{ unit: 'day', step: 1, date: ' %D ,%j' },]// //当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度gantt.config.fit_tasks = true// 添加弹窗属性gantt.config.lightbox.sections = [{name: 'description',height: 70,map_to: 'text',type: 'textarea',focus: true,},{ name: 'type', type: 'typeselect', map_to: 'type' },{ name: 'time', type: 'duration', map_to: 'auto' },];console.log(this.tasks.data, '检查任务数据'); // 检查任务数据// 初始化gantt.init(this.$refs.gantt)/* *******重点******* */gantt.clearAll(); // 清空旧数据/* ****************** */// 数据解析gantt.parse(this.tasks)},
更新数据
loadData(arg) {if (!this.url.list) {this.$message.error("请设置url.list属性!")return}//加载数据 若传入参数1则加载第一页的内容let params = {planId: this.planId,}this.loading = true;this.tasks.data = []getAction(this.url.list, params).then((res) => {if (res.success) {console.log(res, '甘特图数据');res.result.forEach(obj => {obj.open = false})this.tasks.data = res.resultthis.init()}if (res.code === 510) {this.$message.warning(res.message)}this.loading = false;})},
三、代码示例
3.1 Vue2完整示例
<template><div><div ref="gantt" style="height:500px;" /></div>
</template><script>
import gantt from 'dhtmlx-gantt'
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import { getAction, putAction } from '@/api/manage'
export default {props: {planId: {type: String,required: true,}},// mixins: [JeecgListMixin],data() {return {// 甘特图配置tasks: {data: [// {// id: 11,// text: 'Project #1',// // type: gantt.config.types.project,// progress: 0.5,//完成度// open: true,//默认打开// number: '20240227',//显示字段// },// {// toolTipsTxt: '任务#101-001',// id: 12,//任务id// text: '任务#1',//任务名称// start_date: '03-04-2022',//开始时间 日月年// duration: '5',//任务时常// parent: '11',//父级id// progress: 1,//完成度// open: true,//默认打开// },// {// id: 13,// text: '任务#2',// start_date: '03-04-2022',// // type: gantt.config.types.project,// parent: '11',// progress: 0.255,// open: true,// },// {// id: 14,// text: '任务#3',// start_date: '01-04-2022',// duration: '6',// parent: '11',// progress: 0.8,// open: true,// },// {// id: 15,// text: '任务#4',// // type: gantt.config.types.project,// parent: '11',// progress: 0.2,// open: true,// },// {// id: 16,// text: 'Final milestone',// start_date: '15-04-2022',// // type: gantt.config.types.milestone,// parent: '11',// progress: 0,// open: true,// },// {// id: 17,// text: '任务#2.1',// start_date: '03-04-2022',// duration: '2',// parent: '13',// progress: 1,// open: true,// },// {// id: 18,// text: '任务#2.2',// start_date: '06-04-2022',// duration: '3',// parent: '13',// progress: 0.8,// open: true,// },// {// id: 19,// text: '任务#2.3',// start_date: '10-04-2022',// duration: '4',// parent: '13',// progress: 0.2,// open: true,// },// {// id: 20,// text: '任务#2.4',// start_date: '10-04-2022',// duration: '4',// parent: '13',// progress: 0,// open: true,// },// {// id: 21,// text: '任务#4.1',// start_date: '03-04-2022',// duration: '4',// parent: '15',// progress: 0.5,// open: true,// },// {// id: 22,// text: '任务#4.2',// start_date: '03-04-2022',// duration: '4',// parent: '15',// progress: 0.1,// open: true,// },// {// id: 23,// text: 'Mediate milestone',// start_date: '14-04-2022',// // type: gantt.config.types.milestone,// parent: '15',// progress: 0,// open: true,// },],// #字段解释// 格式 id:数据id // source:开始链接的项目id ----为tasks.data中数据的id// target:要链接项目的id ----为tasks.data中数据的id// type: 0--进行-开始 `尾部链接头部` // 1--开始-开始 `头部链接头部`// 2--进行-进行 `尾部链接尾部`// 3--开始-进行 `头部链接尾部`// 任务之间连接links: [{ id: '10', source: '11', target: '12', type: '1' },{ id: '11', source: '11', target: '13', type: '1' },{ id: '12', source: '11', target: '14', type: '1' },{ id: '13', source: '11', target: '15', type: '1' },{ id: '14', source: '23', target: '16', type: '0' },{ id: '15', source: '13', target: '17', type: '1' },{ id: '16', source: '17', target: '18', type: '0' },{ id: '17', source: '18', target: '19', type: '0' },{ id: '18', source: '19', target: '20', type: '0' },{ id: '19', source: '15', target: '21', type: '2' },{ id: '20', source: '15', target: '22', type: '2' },{ id: '21', source: '15', target: '23', type: '0' },],},url: {list: "/projectManage/projectPlan/queryProjectPlanGTT",// delete: "/projectManage/projectModule/delete",// deleteBatch: "/projectManage/projectModule/deleteBatch",// exportXlsUrl: "/projectManage/projectModule/exportXls",// importExcelUrl: "/projectManage/projectModule/importExcel",// budgetExportXlsUrl: "/projectManage/projectModule/budgetExportXls",// budgetImportUrl: "/projectManage/projectModule/budgetImportExcel",},}},watch: {},created() {console.log(this.planId, '参数');},mounted() {this.loadData();},methods: {// 初始化init() {// 格式化日期gantt.locale.date = {month_full: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"],day_full: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],day_short: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]}gantt.locale.labels = {dhx_cal_today_button: "今天",day_tab: "日",week_tab: "周",month_tab: "月",new_event: "新建日程",icon_save: "保存",icon_cancel: "关闭",icon_details: "详细",icon_edit: "编辑",icon_delete: "删除",confirm_closing: "请确认是否撤销修改!", //Your changes will be lost, are your sure?confirm_deleting: "是否删除计划?",section_description: "描述:",section_time: "时间范围:",section_type: "类型:",section_text: "计划名称:",section_test: "测试:",section_projectClass: "项目类型:",taskProjectType_0: "项目任务",taskProjectType_1: "普通任务",section_head: "负责人:",section_priority: '优先级:',taskProgress: '任务状态',taskProgress_0: "未开始",taskProgress_1: "进行中",taskProgress_2: "已完成",taskProgress_3: "已延期",taskProgress_4: "搁置中",section_template: 'Details',/* grid columns */column_text: "计划名称",column_start_date: "开始时间",column_duration: "持续时间",column_add: "",column_priority: "难度",/* link confirmation */link: "关联",confirm_link_deleting: "将被删除",message_ok: '确定',message_cancel: '取消',link_start: " (开始)",link_end: " (结束)",type_task: "任务",type_project: "项目",type_milestone: "里程碑",minutes: "分钟",hours: "小时",days: "天",weeks: "周",months: "月",years: "年"}console.log(gantt);//自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务gantt.config.autosize = true//只读模式gantt.config.readonly = false//是否显示左侧树表格gantt.config.show_grid = true// //表格列设置gantt.config.columns = [{ name: 'text', label: '阶段名字', tree: true, width: '150', align: 'center', },// { name: 'number', label: '工单号', tree: false, width: '120', align: 'center', },{name: 'duration',label: '工时',align: 'center',template: function (obj) {return obj.duration + '天'},},/*{name:"start_date", label:"开始时间", align: "center" },{name:"end_date", label:"结束时间", align: "center" },*/]// 自动延长时间刻度gantt.config.fit_tasks = true// 允许拖放gantt.config.drag_project = true// 定义时间格式gantt.config.scales = [{ unit: 'month', step: 1, date: ' %Y,%F' },{ unit: 'day', step: 1, date: ' %D ,%j' },]// //当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度gantt.config.fit_tasks = true// 添加弹窗属性gantt.config.lightbox.sections = [{name: 'description',height: 70,map_to: 'text',type: 'textarea',focus: true,},{ name: 'type', type: 'typeselect', map_to: 'type' },{ name: 'time', type: 'duration', map_to: 'auto' },];console.log(this.tasks.data, '检查任务数据'); // 检查任务数据// 初始化gantt.init(this.$refs.gantt)/* *******重点******* */gantt.clearAll(); // 清空旧数据/* ****************** */// 数据解析gantt.parse(this.tasks)},loadData(arg) {if (!this.url.list) {this.$message.error("请设置url.list属性!")return}//加载数据 若传入参数1则加载第一页的内容let params = {planId: this.planId,}this.loading = true;this.tasks.data = []getAction(this.url.list, params).then((res) => {if (res.success) {console.log(res, '甘特图数据');res.result.forEach(obj => {obj.open = false})this.tasks.data = res.resultthis.init()}if (res.code === 510) {this.$message.warning(res.message)}this.loading = false;})},},
}
</script><style lang="less" scoped>
.firstLevelTask {border: none;.gantt_task_content {// font-weight: bold;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: 900px;.left-container {height: 100%;}
}.left-container {height: 600px;
}.gantt_scale_line {border-top: 0;
}.weekend {//background:#f4f7f4!important;color: #000000 !important;
}.gantt_selected .weekend {background: #f7eb91 !important;
}.gantt_task_content {text-align: left;padding-left: 10px;
}//上面任务条样式
.gantt_task_scale {height: 45px !important;
}.gantt_task .gantt_task_scale .gantt_scale_cell {line-height: 30px !important;height: 28px !important;
}
</style>
3.2 Vue3 完整示例
<template><div style="height: 100%; background-color: white"><div ref="ganttRef" style="width: 100%; height: 600px"></div></div>
</template><script setup name="gantt-widget">
import { ref, reactive, onMounted } from 'vue'
import { gantt } from 'dhtmlx-gantt'
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
import { formatDate } from '@/utils/util.js'import { defineProps } from 'vue'
const props = defineProps({widgetObj: {type: Object,required: true,},
})const ganttRef = ref()
const tasks = ref({})//动态加载数据
const fetchData = () => {tasks.value = tasks.value = {tasks: [{id: 10,text: 'RFQ&项目启动',type: 'project',progress: 0.1,open: true,person: '张三',},{id: 12,text: '产品需求 #1.0.1',start_date: '02-01-2025',duration: 3,parent: 10,progress: 1,person: '张三',},{id: 13,text: '产品数据 #1.0.2',start_date: '05-01-2025',duration: 3,parent: 10,progress: 0.8,person: '张三',},{id: 14,text: '环境数据 #1.0.3',start_date: '08-01-2025',duration: 3,parent: 10,progress: 0,person: '张三',},{id: 15,text: '项目评估指令 #1.1',start_date: '11-01-2025',duration: 3,parent: 10,progress: 0,person: '张三',},{id: 16,text: '成立项目小组 #1.2.1',start_date: '12-01-2025',duration: 2,parent: 10,progress: 0,person: '张三',},{id: 17,text: '可行性评估 #1.2.2',start_date: '13-01-2025',duration: 3,parent: 10,progress: 0,person: '张三',},{id: 18,text: '输入评审 #1.2.3',start_date: '14-01-2025',duration: 2,parent: 10,progress: 0,person: '张三',},{id: 19,text: '初始产品方案 #1.2.4',start_date: '16-01-2025',duration: 2,parent: 10,progress: 0,person: '张三',},{id: 20,text: '产品设计&开发',type: 'project',progress: 0,person: '张三',open: false,},{id: 21,text: '设计输入信息管理#3.0.1',start_date: '18-01-2025',duration: 2,parent: 20,progress: 0,person: '张三',},{id: 22,text: '产品设计过往教训展开 #3.0.2',start_date: '20-01-2025',duration: 2,parent: 20,progress: 0,person: '张三',},{id: 23,text: '产品设计进度管理 #3.0.3',start_date: '22-01-2025',duration: 2,parent: 20,progress: 0,person: '张三',},{id: 24,text: '产品设计方案 #3.0.4',start_date: '24-01-2025',duration: 2,parent: 20,progress: 0,person: '张三',},{id: 25,text: '产品特殊特性识别 #3.0.5',start_date: '26-01-2025',duration: 2,parent: 20,progress: 0,person: '张三',},{id: 26,text: '产品设计方案评审 #3.0.6',start_date: '28-01-2025',duration: 2,parent: 20,progress: 0,person: '张三',},{id: 30,text: '过程设计&开发',type: 'project',progress: 0,person: '张三',open: false,},{id: 31,text: '场地规划 #5.0.1',start_date: '28-02-2025',duration: 3,parent: 30,progress: 0,person: '张三',},{id: 32,text: '场地评审 #5.0.2',start_date: '28-02-2025',duration: 3,parent: 30,progress: 0,person: '张三',},{id: 33,text: '过程检验标准 #5.0.3',start_date: '29-02-2025',duration: 3,parent: 30,progress: 0,person: '张三',},{id: 40,text: '产品&过程验证',type: 'project',open: false,progress: 0,person: '张三',},{id: 41,text: '量具重复再现性分析 #6.0.1',start_date: '29-02-2025',duration: 3,parent: 40,progress: 0,person: '张三',},{id: 42,text: '检具使用验收 #6.0.2',start_date: '01-03-2025',duration: 3,parent: 40,progress: 0,person: '张三',},{id: 43,text: '工装-厂外预验收 #6.1.1',start_date: '02-03-2025',duration: 3,parent: 40,progress: 0,person: '张三',},{id: 44,text: '设备-厂外预验收 #6.2.1',start_date: '03-03-2025',duration: 3,parent: 40,progress: 0,person: '张三',},{id: 45,text: '模具-厂外预验收 #6.3.1',start_date: '04-03-2025',duration: 3,parent: 40,progress: 0,person: '张三',},{id: 50,text: '过程验证',type: 'project',open: false,progress: 0,person: '张三',},{id: 51,text: '小批量试生产总结 #7.0.1',start_date: '28-04-2025',duration: 3,parent: 50,progress: 0,person: '张三',},{id: 52,text: '产品尺寸记录 #7.0.2',start_date: '29-04-2025',duration: 3,parent: 50,progress: 0,person: '张三',},{id: 52,text: '过程能力研究 #7.0.3',start_date: '30-04-2025',duration: 3,parent: 50,progress: 0,person: '张三',},{id: 60,text: '反馈,纠正和改进',type: 'project',open: false,progress: 0,person: '张三',},{id: 61,text: '模工检移交 #8.0.1',start_date: '28-05-2025',duration: 3,parent: 60,progress: 0,person: '张三',},{id: 62,text: '项目移交会议 #8.0.2',start_date: '29-05-2025',duration: 3,parent: 60,progress: 0,person: '张三',},{id: 63,text: '取得量产交付计划 #8.1.1',start_date: '30-05-2025',duration: 3,parent: 60,progress: 0,person: '张三',},],links: [{ id: 10, source: 12, target: 13, type: 1 },{ id: 11, source: 13, target: 14, type: 1 },{ id: 12, source: 14, target: 15, type: 1 },],}
}//初始化配置
const initGantt = () => {gantt.plugins({ tooltip: true, quick_info: true })// 汉化窗口gantt.locale.labels = {dhx_cal_today_button: '今天',day_tab: '日',week_tab: '周',month_tab: '月',new_event: '新建日程',icon_save: '保存',icon_cancel: '关闭',icon_details: '详细',icon_edit: '编辑',icon_delete: '删除',confirm_closing: '请确认是否撤销修改!', //Your changes will be lost, are your sure?confirm_deleting: '是否删除计划?',section_description: '描述:',section_time: '时间范围:',section_type: '类型:',section_text: '计划名称:',section_test: '测试:',section_projectClass: '项目类型:',taskProjectType_0: '项目任务',taskProjectType_1: '普通任务',section_head: '负责人:',section_priority: '优先级:',taskProgress: '任务状态',taskProgress_0: '未开始',taskProgress_1: '进行中',taskProgress_2: '已完成',taskProgress_3: '已延期',taskProgress_4: '搁置中',section_template: 'Details',/* grid columns */column_text: '计划名称',column_start_date: '开始时间',column_duration: '持续时间',column_add: '',column_priority: '难度',/* link confirmation */link: '关联',confirm_link_deleting: '将被删除',message_ok: '确定',message_cancel: '取消',link_start: ' (开始)',link_end: ' (结束)',type_task: '任务',type_project: '项目',type_milestone: '里程碑',minutes: '分钟',hours: '小时',days: '天',weeks: '周',months: '月',years: '年',}// 格式化日期gantt.locale.date = {month_full: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月',],month_short: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月',],day_full: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六',],day_short: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六',],}// 当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度gantt.config.fit_tasks = true// 允许拖放gantt.config.drag_project = true// 定义时间格式gantt.config.scales = [{ unit: 'month', step: 1, date: '%F, %Y' },{ unit: 'day', step: 1, date: '%j, %D' },]// gantt.config.scale_height = 80// gantt.config.row_height = 60// gantt.config.bar_height = 40gantt.i18n.setLocale('cn')// gantt.config.autosize = true// gantt.config.readonly = truegantt.config.show_grid = truegantt.config.show_task_tooltips = truegantt.config.show_progress = truegantt.config.branches = {open: 'open',closed: 'closed',}gantt.templates.tooltip_text = (start, end, task) => `<div><div>任务:${task.text}</div><div>开始时间:${formatDate(task.start_date, '{y}-{m}-{d}')}</div><div>结束时间:${formatDate(task.end_date, '{y}-{m}-{d}')}</div><div>进度:${task.progress * 100}%</div></div>`gantt.config.columns = [{name: 'text',label: '任务名称',width: '250',tree: true,align: 'left',},{ name: 'start_date', label: '起始时间', width: '100', align: 'center' },{ name: 'duration', label: '持续时间', width: '80', align: 'center' },{name: 'progress',label: '进度',width: '100',align: 'center',template: function (obj) {return obj.progress * 100 + '%'},},{ name: 'person', label: '负责人', width: '80', align: 'center' },]gantt.config.lightbox_zindex = 10000// 添加弹窗属性gantt.config.lightbox.sections = [{name: 'description',height: 70,map_to: 'text',type: 'textarea',focus: true,},{ name: 'type', type: 'typeselect', map_to: 'type' },{ name: 'time', type: 'duration', map_to: 'auto' },]// 初始化gantt.init(ganttRef.value)// 清空旧数据gantt.clearAll()// 数据解析gantt.parse(tasks.value)
}onMounted(() => {fetchData()initGantt()
})
</script><style lang="scss" scoped>
.gantt_cal_light {z-index: 9999 !important;
}
.gantt_cal_cover {z-index: 10000 !important;
}
</style>
四、效果图

相关文章:
vue+dhtmlx-gantt 实现甘特图-快速入门【甘特图】
文章目录 一、前言二、使用说明2.1 引入依赖2.2 引入组件2.3 引入dhtmlx-gantt2.4 甘特图数据配置2.5 初始化配置 三、代码示例3.1 Vue2完整示例3.2 Vue3 完整示例 四、效果图 一、前言 dhtmlxGantt 是一款功能强大的甘特图组件,支持 Vue 3 集成。它提供了丰富的功…...
游戏引擎学习第147天
仓库:https://gitee.com/mrxiao_com/2d_game_3 上一集回顾 具体来说,我们通过隐式计算来解决问题,而不是像数字微分分析器那样逐步增加数据。我们已经涵盖了这个部分,并计划继续处理音量问题。不过,实际上我们现在不需要继续处理…...
Python自动点击器开发教程 - 支持键盘连按和鼠标连点
Python自动点击器开发教程 - 支持键盘连按和鼠标连点 这里写目录标题 Python自动点击器开发教程 - 支持键盘连按和鼠标连点项目介绍开发环境安装依赖核心代码解析1. 键盘模拟实现2. 鼠标点击实现 开发要点使用说明注意事项优化建议打包发布项目源码开发心得参考资料成品工具 项…...
C++ 链表List使用与实现:拷贝交换与高效迭代器细致讲解
目录 list的使用: 构造与赋值 元素访问 修改操作 容量查询 链表特有操作 拼接(Splice) C11 新增方法 注意: stl_list的模拟实现: 一、链表节点设计的艺术 1.1 结构体 vs 类的选择 二、迭代器实现的精髓 2…...
Manus联创澄清:我们并未使用MCP技术
摘要 近日,Manus联创针对外界关于其产品可能涉及“沙盒越狱”的疑问进行了正式回应。公司明确表示并未使用Anthropic的MCP(模型上下文协议)技术,并强调MCP是一个旨在标准化应用程序与大型语言模型(LLM)之间…...
ACE学习2——write transaction
用于处理缓存行的数据更新到主内存(main memory)的操作。 以下是用于更新主内存的几种事务类型: WriteBack: WriteBack事务用于将cache中的dirty态的cacheline写回主存,以释放cache中的cacheline,用于存…...
c++ 返回引用
在C中,返回引用是一种常见的做法,特别是在需要返回大型对象时,以避免不必要的复制,从而提高程序的效率。返回引用通常有两种情况:返回局部变量的引用和返回成员变量的引用。下面分别讨论这两种情况以及如何安全地实现它…...
Docker篇
1.docker环境搭建: 1.1软件仓库的配置rhel9: #cd/etc/yum.repos.d #vim docker.repo [docker] namedocker-ce baseurlhttps://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable gpgcheck0 1.2安装docker并且启动服务 yum install -y dock…...
TypeScript基础类型详解:与JavaScript的对比与核心价值
TypeScript作为JavaScript的超集,最大的特性是引入了静态类型系统。本文将基于TypeScript官网内容,解析其基础类型设计,并与ES/JavaScript进行对比,揭示类型系统的实际价值。 一、基础类型全景图 1. 原生类型的强化 JavaScript原…...
Linux《基础开发工具(中)》
在之前的Linux《基础开发工具(上)》当中已经了解了Linux当中到的两大基础的开发工具yum与vim;了解了在Linux当中如何进行软件的下载以及实现的基本原理、知道了编辑器vim的基本使用方式,那么接下来在本篇当中将接下去继续来了解另…...
CPU 负载 和 CPU利用率 的区别
简单记录下 top 命令中,CPU利用率核CPU负载的概念, (1)CPU利用率:指在一段时间内 表示 CPU 实际工作时间占总时间的百分比。表示正在执行进程的时间比例,包括用户空间和内核空间程序的执行时间。通常包含以…...
vue源码(二)
文章目录 数据代理示例 初始化组件实例计算属性基本用法ComputedReflmpl类计算属性的创建 Vue3的特点及优势声明式框架采用虚拟DOM区分编译时和进行时 Vue3设计思想 数据代理 示例 以下代码主要是有一个msg的响应式数据,点击按钮后修改msg的内容。根据代码可知有两…...
Ubuntu切换lowlatency内核
文章目录 一. 前言二. 开发环境三. 具体操作 一. 前言 低延迟内核(Lowlatency Kernel) 旨在为需要低延迟响应的应用程序设计的内核版本。Linux-lowlatency特别适合音频处理、实时计算、游戏和其他需要及时响应的实时任务。其主要特点是优化了中断处理、调…...
C++算法——差分
1.差分 差分与前缀和的核心思想相同,是预处理,可以在暴力枚举的过程中,快速给出查询的结果,从而优化时间复杂度。 是经典的用空间替换时间的做法。 2.一维差分数组 前缀和与差分是⼀对互逆的运算,对差分数组做前缀…...
猫耳大型活动提效——组件低代码化
1. 引言 猫耳前端在开发活动的过程中,经历过传统的 pro code 阶段,即活动页面完全由前端开发编码实现,直到 2020 年接入公司内部的低代码活动平台,满足了大部分日常活动的需求,运营可自主配置活动并上线,释…...
亿级分布式系统架构演进实战(二)- 横向扩展(服务无状态化)
亿级分布式系统架构演进实战(一)- 总体概要 服务无状态化详细设计 目标:确保服务实例完全无状态,可任意扩缩容 1. 会话存储改造(Session Management) 核心问题:传统单体应用中,用…...
零成本短视频爆款制造手册
——Q版+情感+互动的流量密码拆解 适用平台:抖音/快手/视频号 核心指标:点赞率>10% | 完播率>40% | 涨粉成本<0.3元 一、底层逻辑框架 1. 爆款元素融合公式 [ 3秒钩子 ] + [ 7秒沉浸 ] + [ 5秒引爆 ] = 15秒黄金结构 │ │ └─▶ 互动指令+情感…...
红队思想:Live off the Land - 靠山吃山,靠水吃水
在网络安全领域,尤其是红队(Red Team)渗透测试中,“Live off the Land”(简称 LotL,中文可译为“靠山吃山,靠水吃水”)是一种极具隐秘性和实用性的攻击策略。这一理念源于现实生活中…...
C语言八股---预处理,编译,汇编与链接篇
前言 从多个.c文件到达一个可执行文件的四步: 预处理–>编译–>汇编–>链接 预处理 预处理过程就是预处理器处理这些预处理指令(要不然编译器完全不认识),最终会生成 main.i的文件 主要做的事情有如下几点: 展开头文件展开宏条件编译删除注释添加行号等信息保留…...
平衡二叉树(AVL树)
平衡二叉树是啥我就不多说了,本篇博客只讲原理与方法。 首先引入平衡因子的概念。平衡因子(Balance Factor),以下简称bf。 bf 右子树深度 - 左子树深度。平衡结点的平衡因子可为:-1,0,1。除此…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
