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
:父级id
start_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。除此…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...