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 集成。它提供了丰富的功…...
关于ModbusTCP/RTU协议对接Ethernet/IP(CIP)协议的方案
IGT-DSER智能网关模块支持西门子、倍福(BECKHOFF)、罗克韦尔AB,以及三菱、欧姆龙等各种品牌的PLC之间通讯,支持Ethernet/IP(CIP)、Profinet(S7),以及FINS、MC等工业自动化常用协议,同时也支持PLC与Modbus协议的工业机器人、智能仪…...
python-leetcode 49.二叉树中的最大路径和
题目: 二叉树中的路径被定义为一条节点序列,序列中每对相邻节点之间都存在一条边,同一个节点在一条路径序列中至多出现一次,该路径至少包含一个节点,且不一定经过根节点。 路径和是路径中各节点值得总和,…...
C语言基础知识04
指针 指针概念 指针保存地址,地址是字节的编号 指针类型和保存的地址类型要一直 使用时注意,把地址转换为&变量的格式来看 int a[3]; a转为&a[0] 指针的大小 64bit 固定8字节, 32bit 固定4字节 指针…...
使用 Golang 操作 MySQL
在Go语言中,操作SQL数据库,通常会用到一些第三方库来简化数据库的连接、查询和操作过程。其中原生的 database/sql go-sql-driver/mysql 库更符合sql语句使用习惯。 安装 go get github.com/go-sql-driver/mysql 直接上代码来演示基本的创建ÿ…...
前端面试:cookie 可以实现不同域共享吗?
在前端开发中,Cookie 不能直接实现不同域之间的共享。Cookie 的作用域受到域的限制,浏览器不会允许一个域下的 Cookie 被另一个域访问。这是为了保护用户隐私及安全,防止跨站请求伪造(CSRF)等安全问题。 Cookie 的基本…...
MyBatis-Plus接入和简单使用
如何接入 https://baomidou.com/getting-started/ 简单使用方法 使用 MyBatis-Plus 时,大多数场景下不需要编写 XML 和 SQL,因为它提供了强大的通用 CRUD 操作和条件构造器。但以下情况可能需要手动编写 SQL: 1. 不需要写 XML/SQL 的场景 …...
【Go万字洗髓经】Golang内存模型与内存分配管理
本文目录 1. 操作系统中的虚拟内存分页与进程管理虚拟内存与内存隔离 2. Golang中的内存模型内存分配流程内存单元mspan线程缓存mcache中心缓存mcentral全局堆缓存mheapheapArena空闲页索引pageAlloc 3. Go对象分配mallocgc函数tiny对象分配内存 4.结合GMP模型来看内存模型tiny…...
mov格式视频如何转换mp4?
mov格式视频如何转换mp4?在日常的视频处理中,经常需要将MOV格式的视频转换为MP4格式,以兼容更多的播放设备和平台。下面给大家分享如何将MOV视频转换为MP4,4款视频格式转换工具分享。 一、牛学长转码大师 牛学长转码大师是一款功…...
鸿蒙OS开发ForEach循环渲染
摘要 在ForEach循环渲染过程中,如果修改列表项中的数据,但是UI页面不会刷新。在最近开发公司app时遇到了这个问题,经过查看官方文档找到了解决方式 官方地址:数据变化不刷新 一、具体解决方案 思路:通过父子组件传…...
【算法】DFS、BFS、拓扑排序
⭐️个人主页:小羊 ⭐️所属专栏:算法 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 持续更新中...1、DFS2、BFSN 叉树的层序遍历二叉树的锯齿形层序遍历二叉树最大宽度 3、多源BFS腐烂的苹果 4、拓扑排序 持续更新中…...
【Godot4.0】贝塞尔曲线在游戏中的实际应用
概述 之前研究贝塞尔曲线绘制,完全是以绘图函数,以及实现节点连接为思考。并没有实际考虑贝塞尔曲线在游戏中的应用。今日偶然看到悦千简一年多前发的一个用贝塞尔曲线实现追踪弹或箭矢效果,还有玩物不丧志的老李杀戮尖塔系列中的卡牌动态箭…...
MongoDB 数据导出与导入实战指南(附完整命令)
1. 场景说明 在 MongoDB 运维中,数据备份与恢复是核心操作。本文使用 mongodump 和 mongorestore 工具,演示如何通过命令行导出和导入数据,解决副本集连接、路径指定等关键问题。 2. 数据导出(mongodump) 2.1 导出命…...
『Rust』Rust运行环境搭建
文章目录 rust编译工具rustupVisual Studio VS Code测试编译手动编译VSCode编译配置 参考完 rust编译工具rustup https://www.rust-lang.org/zh-CN/tools/install 换源 RUSTUP_DIST_SERVER https://rsproxy.cn RUSTUP_UPDATE_ROOT https://rsproxy.cn修改rustup和cargo的安…...
CPU+GPU结合的主板设计思路与应用探讨
在高性能计算和图形处理需求不断增长的背景下,CPUGPU结合的主板设计逐渐成为硬件架构的重要趋势。本文将探讨基于CPUGPU架构的主板设计思路、关键技术考量以及应用前景。 1. 设计思路概述 CPU(中央处理器)擅长处理复杂的逻辑运算和多任务控制…...
latex问题汇总
latex问题汇总 环境问题1 环境 texlive2024 TeXstudio 4.8.6 (git 4.8.6) 问题1 编译过程有如下错 ! Misplaced alignment tab character &. l.173 International Conference on Infrared &Millimeter Waves, 2004: 667--... I cant figure out why you would wa…...
学习springboot-Bean管理(Bean 注册,Bean 扫描)
Bean 扫描 可以浏览下面的博客链接 :spring 学习 (注解)-CSDN博客 在学习spring 注解时,我们使用 Component ,Service,Controller等 这样的注解,将目标类信息,传递给IOC容器,为其创…...
iOS开发,SQLite.swift, Missing argument label ‘value:‘ in call问题
Xcode16中,集成使用SQLite.swift,创建表的时候: let id Expression<Int64>("id"),报错Missing argument label value: in call 直接使用SQLite.Expression<Int64>("id") 或者定义一个全局typ…...
【GIT】重新初始化远程仓库
有的时候我们克隆远端仓库会出错: git clone --depth 1 git116.*.*.*:/srv/customs.git D:\dev\projects\kdy\customs11\customs Cloning into D:\dev\projects\kdy\customs11\customs... remote: Enumerating objects: 1494, done. remote: Counting objects: 100…...
Vue3中 ref 与 reactive区别
ref 用途: ref 通常用于创建一个响应式的基本类型数据(如 string、number、boolean 等),但它也可以用于对象或数组 返回值: ref 返回一个带有 .value 属性的对象,访问或修改数据需要通过 .value 进行 使用场景: …...
apollo3录音到wav播放解决方法
SDK DEMO项目:ap3bp_evb_vos_pcm_recorder_20210901 pcm_recorder.c //***************************************************************************** // // Options // //***************************************************************************** #define PRINT…...
信号处理抽取多项滤波的数学推导与仿真
昨天的《信号处理之插值、抽取与多项滤波》,已经介绍了插值抽取的多项滤率,今天详细介绍多项滤波的数学推导,并附上实战仿真代码。 一、数学变换推导 1. 多相分解的核心思想 将FIR滤波器的系数 h ( n ) h(n) h(n)按相位分组,每…...
Java网络多线程
网络相关概念: 关于访问: IP端口 因为一个主机上可能有多个服务, 一个服务监听一个端口,当你访问的时候主机通过端口号就能知道要和哪个端口发生通讯.因此一个主机上不能有两个及以上的服务监听同一个端口. 协议简单来说就是数据的组织形式 好像是两个人交流一样,要保证自己说…...
linux centos 忘记root密码拯救
在CentOS 7中,如果忘记root密码,可以通过修改系统启动参数进入单用户模式或紧急模式进行重置。以下是两种常用方法,适用于物理机或虚拟机环境: 方法一:通过rd.break参数重置密码 步骤: 重启系统并进入GRU…...
C# 事件使用详解
总目录 前言 在C#中,事件(Events)是一种基于委托的重要机制,用于实现对象之间的松耦合通信。它通过发布-订阅模式(Publisher-Subscriber Pattern),允许一个对象(发布者)…...
flink cdc同步mysql数据
一、api 添加依赖 <dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-mysql-cdc</artifactId><!-- 请使用已发布的版本依赖,snapshot 版本的依赖需要本地自行编译。 --><version>3.3-SNAP…...
tomcat负载均衡配置
这里拿Nginx和之前做的Tomcat 多实例来实现tomcat负载均衡 1.准备多实例与nginx tomcat单机多实例部署-CSDN博客 2.配置nginx做负载均衡 upstream tomcat{ server 192.168.60.11:8081; server 192.168.60.11:8082; server 192.168.60.11:8083; } ser…...
Ceph(1):分布式存储技术简介
1 分布式存储技术简介 1.1 分布式存储系统的特性 (1)可扩展 分布式存储系统可以扩展到几百台甚至几千台的集群规模,而且随着集群规模的增长,系统整体性能表现为线性增长。分布式存储的水平扩展有以下几个特性: 节点…...
16、JavaEE核心技术-EL与 JSTL
EL与 JSTL 实践 一. EL(Expression Language) EL(表达式语言)是 JSP 2.0 中引入的一种简单的脚本语言,用于在 JSP 页面中简化数据的访问和显示。它通过一种类似于 JavaScript 的语法,允许开发者在 JSP 页面…...
RabbitMQ报错:Shutdown Signal channel error; protocol method
报错信息: Shutdown Signal: channel error; protocol method: #method<channel.close>(reply-code406, reply-textPRECONDITION_FAILED - unknown delivery tag 1, class-id60, method-id80) 原因 默认情况下 RabbitMQ 是自动ACK(确认签收&…...
使用DeepSeek完成一个简单嵌入式开发
开启DeepSeek对话 请帮我使用Altium Designer设计原理图、PCB,使用keil完成代码编写;要求:使用stm32F103RCT6为主控芯片,控制3个流水灯的原理图 这里需要注意,每次DeepSeek的回答都不太一样。 DeepSeek回答 以下是使…...
NLP技术介绍
NLP技术介绍 语言分析技术分词词性标注命令实体识别句法分析语义分析文本处理技术文本分类文本聚类情感分析文本生成机器翻译对话系统与交互技术聊天机器人问答系统语音识别与合成知识图谱与语义理解技术知识图谱语义搜索语义推理深度学习与预训练模型循环神经网络(RNN)及其变…...
pycharm + anaconda + yolo11(ultralytics) 的视频流实时检测,保存推流简单实现
目录 背景pycharm安装配置代码实现创建本地视频配置 和 推流配置视频帧的处理和检测框绘制主要流程遇到的一些问题 背景 首先这个基于完整安装配置了anaconda和yolo11的环境,如果需要配置开始的话,先看下专栏里另一个文章。 这次的目的是实现拉取视频流…...
C++编译问题——1模板函数的实现必须在头文件中
今天编译数据结构时,遇见一个编译错误 假设你有一个头文件 SeqList.h 和一个源文件 SeqList.cpp。 SeqList.h #ifndef SEQLIST_H #define SEQLIST_H#include <stdexcept> #include <iostream>template<typename T> class SeqList { private:sta…...
深度学习PyTorch之数据加载DataLoader
深度学习pytorch之简单方法自定义9类卷积即插即用 文章目录 数据加载基础架构1、Dataset类详解2、DataLoader核心参数解析3、数据增强 数据加载基础架构 核心类关系图 torch.utils.data ├── Dataset (抽象基类) ├── DataLoader (数据加载器) ├── Sampler (采样策略)…...
使用Beanshell前置处理器对Jmeter的请求body进行加密
这里我们用HmacSHA256来进行加密举例: 步骤: 1.先获取请求参数并对请求参数进行处理(处理成String类型) //处理请求参数的两种方法: //方法一: //获取请求 Arguments args sampler.getArguments(); //转…...
前端面试:如何减少项目里面 if-else?
在前端开发中,大量使用 if-else 结构可能导致代码调试困难、可读性降低和冗长的逻辑。不妨考虑以下多种策略来减少项目中的 if-else 语句,提高代码的可维护性和可读性: 1. 使用对象字面量替代 用对象字面量来替代 if-else 语句,…...
05.基于 TCP 的远程计算器:从协议设计到高并发实现
📖 目录 📌 前言🔍 需求分析 🤔 我们需要解决哪些问题? 🎯 方案设计 💡 服务器架构 🚀 什么是协议?为什么要设计协议? 📌 结构化数据的传输问题 …...
Matlab:矩阵运算篇——矩阵数学运算
目录 1.矩阵的加法运算 实例——验证加法法则 实例——矩阵求和 实例——矩阵求差 2.矩阵的乘法运算 1.数乘运算 2.乘运算 3.点乘运算 实例——矩阵乘法运算 3.矩阵的除法运算 1.左除运算 实例——验证矩阵的除法 2.右除运算 实例——矩阵的除法 ヾ( ̄…...
git reset的使用,以及解决还原后如何找回
文章目录 git reset 详解命令作用常用参数1. --soft2. --mixed(默认参数,可省略)3. --hard4. 提交引用 总结 git reset --hard HEAD^ 还原代码如何找回?利用 git reflog找回 git reset 详解 git reset 是 Git 中一个功能强大且较…...
react中字段响应式
class中用法: import React, { Component } from react export default class Index extends Component<any, any> { constructor(props) { super(props) this.state { settingInfo: {}, } } async componentDidMount() { let settingInfo awa…...
vue中,watch里,this为undefined的两种解决办法
提示:vue中,watch里,this为undefined的两种解决办法 文章目录 [TOC](文章目录) 前言一、问题二、方法1——使用function函数代替箭头函数()>{}三、方法2——使用that总结 前言 尽量使用方法1——使用function函数代替箭头函数()…...
智能客服意图识别:结合知识库数据构建训练语料的专业流程
智能客服意图识别:结合知识库数据构建训练语料的专业流程 构建基于知识库的智能客服意图识别模型,需要综合运用 NLP(自然语言处理)、知识图谱、机器学习 等技术,确保意图识别的准确性和覆盖度。以下是专业的流程&…...
Spring Boot集成Spring Statemachine
Spring Statemachine 是 Spring 框架下的一个模块,用于简化状态机的创建和管理,它允许开发者使用 Spring 的特性(如依赖注入、AOP 等)来构建复杂的状态机应用。以下是关于 Spring Statemachine 的详细介绍: 主要特性 …...
压缩空气储能仿真simulink模型
压缩空气储能仿真simulink模型,适合matlab 2017及以上版本 CompressingGas.slx , 40474...
Tomcat 安装
一、Tomcat 下载 官网:Apache Tomcat - Welcome! 1.1.下载安装包 下载安装包: wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.102/bin/apache-tomcat-9.0.102.tar.gz 安装 javajdk。 yum install java-1.8.0-openjdk.x86_64 -y /etc/altern…...
贪心算法和遗传算法优劣对比——c#
项目背景:某钢管厂的钢筋原材料为 55米,工作需要需切割 40 米(1段)、11 米(15 段)等 4 种规格 ,现用贪心算法和遗传算法两种算法进行计算: 第一局:{ 40, 1 }, { 11, 15…...
系统开发资源
一、前端篇 1.1 菜鸟CSS教程 1.2 HTML/CSS/JS 在线工具 二、后端篇 三、其他篇 3.1 菜鸟官网 3.2 黑马程序员学习路线 3.3 根据地区获取经纬度...
深度学习 bert与Transformer的区别联系
BERT(Bidirectional Encoder Representations from Transformers)和Transformer都是现代自然语言处理(NLP)中的重要概念,但它们代表不同的层面。理解这两者之间的区别与联系有助于更好地掌握它们在NLP任务中的应用。 …...
unity使用mesh 画图(1)
plane 圆 空心椭圆 椭圆 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class DrawMeshManager {static DrawMeshManager instance;public static DrawMeshManager Instance {get {if (instance ! null){retu…...