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。除此…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
window 显示驱动开发-如何查询视频处理功能(三)
D3DDDICAPS_GETPROCAMPRANGE请求类型 UMD 返回指向 DXVADDI_VALUERANGE 结构的指针,该结构包含特定视频流上特定 ProcAmp 控件属性允许的值范围。 Direct3D 运行时在D3DDDIARG_GETCAPS的 pInfo 成员指向的变量中为特定视频流的 ProcAmp 控件属性指定DXVADDI_QUER…...