公司的甘特图需求,研究了几个组件后,选择使用 dhtmlx-gantt 进行实现,dhtmlx-gantt使用其实是偏简单的,文档虽然是英文,但配合翻译也是可以看懂的,下面将公司需求的代码实现粘贴出来,并简单介绍一下使用方法,希望对你有帮助。
看一下目前实现的效果:
需求是不需要bar连线的,所以将bar连线注释掉了,连线也是可以有的
组件官网地址: https://dhtmlx.com/
目录
一、首先 npm 安装插件
二、创建一个vue组件
三、业务页面内 引用自定义组件:
四、dhtmlx-gantt 基本配置项
格式化表头日期展示:
甘特图的尺寸自适应
只读模式
是否显示左侧表格
设置表头高度
设置bar的高度
设置行的高度
设置时间识别格式
表格列设置
为每个bar增加class
自动延长时间刻度
允许拖放
定义x轴时间维度
自动调整坐标轴
启用 tooltip 功能
性能提升
增加事件
五、完整代码
下面正式进入教程:
一、首先 npm 安装插件
npm i dhtmlx-gantt
复制
二、创建一个vue组件
我这里命名为gantt.vue ,放在项目根目录的 /components 目录下
gantt.vue文件:
<template> <div> <div ref="gantt"/> </div> </template> <script> import gantt from 'dhtmlx-gantt'; // 引入包 import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'; // 引入自带的css文件 export default { data() { return { tasks: { data: [ { id: 1, text: 'DFB24019', progress: 0.8, //完成度 start_date: '2021-10-16', //开始时间 日月年 end_date: '2021-10-15', projectStatus: '进行中', open: true, //默认打开= number: '', //显示字段 person: '韩鸿风', post: 'BA', department: '数字化一部', task: '0/20' }, { // toolTipsTxt: '任务#101-001', id: 21, //任务id text: '任务1的撒的防守打法士大夫', //任务名称 start_date: '2021-10-16', //开始时间 日月年 end_date: '2021-12-26', parent: 1, //父级id progress: 1, //完成度 open: true, //默认打开 status: '已完成', }, { // toolTipsTxt: '任务#101-001', id: 22, //任务id text: '第二个逾期阶段', //任务名称 start_date: '2021-12-16', //开始时间 日月年 end_date: '2022-01-26', parent: 1, //父级id progress: 1, //完成度 open: true, //默认打开 status: '逾期' }, { // toolTipsTxt: '任务#101-001', id: 23, //任务id text: '第三个进行中阶段', //任务名称 start_date: '2022-01-20', //开始时间 日月年 end_date: '2022-03-03', parent: 1, //父级id progress: 0.7, //完成度 open: true, //默认打开 status: '进行中' }, { id: 2, text: 'DFB45113', progress: 0.7, //完成度 start_date: '2021-10-16', //开始时间 日月年 projectStatus: '已完成', end_date: '2021-10-15', open: true, //默认打开 number: '哈哈哈' //显示字段 }, { // toolTipsTxt: '任务#101-001', id: 11, //任务id text: '项目启动阶段', //任务名称 start_date: '2022-04-06', //开始时间 日月年 end_date: '2022-06-06', parent: 2, //父级id progress: 1, //完成度 open: true, //默认打开 status: '已完成' }, { // toolTipsTxt: '任务#101-001', id: 12, //任务id text: '设计阶段', //任务名称 start_date: '2022-04-20', //开始时间 日月年 end_date: '2022-06-26', parent: 2, //父级id progress: 0.9, //完成度 open: true, //默认打开 status: '进行中' }, { // toolTipsTxt: '任务#101-001', id: 13, //任务id text: '采购阶段', //任务名称 start_date: '2022-05-14', //开始时间 日月年 end_date: '2022-07-26', parent: 2, //父级id progress: 1, //完成度 open: true, //默认打开 status: '未开始' } ], // 任务之间连接线,目前注释掉了,需要的话打开 // 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' } // ] }, }; }, mounted() { this.init(); }, methods: { init() { // 设置时间识别格式 gantt.config.xml_date = "%Y-%m-%d" // //表格列设置 gantt.config.columns = [ { name: 'person', label: '项目成员', width: '100', align: 'center' } ]; gantt.config.scales = [{ unit: 'month', step: 1, date: ' %Y 年 %F' }, { unit: 'day', step: 1, date: '%d' }]; // 清空旧数据 gantt.clearAll(); // 销毁gantt实例 按需开启 // gantt.destructor() // 初始化 gantt.init(this.$refs.gantt); // 数据解析 gantt.parse(this.tasks); }, } </script>
复制
三、业务页面内 引用自定义组件:
<template> <!-- 使用甘特图组件 --> <div style="padding: 10px;background-color: #fff;"> <gantt></gantt> </div> </template> <script> import gantt from '@/components/gantt.vue'; components: { gantt }, </script>
复制
如果你的页面能展示出来基本样式,那么就成功啦,咱们继续下一步
下面讲一下 dhtmlx-gantt 的一些配置项,也可以说是我用到的配置项,更多的就要参考官方文档了
四、dhtmlx-gantt 基本配置项
(注意,都要放在组件的 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.config.autosize = false;
复制
只读模式
为false时支持编辑
gantt.config.readonly = true;
复制
是否显示左侧表格
gantt.config.show_grid = true;
复制
设置表头高度
gantt.config.scale_height = 50;
复制
设置bar的高度
gantt.config.bar_height = 26;
复制
设置行的高度
gantt.config.row_height = 32;
复制
设置时间识别格式
很重要,必须和你数据的格式一样
gantt.config.xml_date = "%Y-%m-%d %H:%i"
复制
表格列设置
(配置项不用细说了吧,template 可以自定义列模板)
gantt.config.columns = [ { name: 'text', label: '项目名称', tree: true, width: '200', align: 'left', template: (task)=>{ if(task.parent) { return task.text } else { return `<div style="font-weight: 700">${task.text}</div>` } }}, { name: 'person', label: '项目成员', width: '100', align: 'center' }, // { name: 'post', label: '岗位名称', width: '100', align: 'center' }, // { name: 'department', label: '部门名称', width: '100', align: 'center' }, { name: 'task', label: '项目任务', width: '100', 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" }, ];
复制
为每个bar增加class
(希望不同的bar展示不同的颜色)
gantt.templates.task_class = function(start, end, item) { switch (item.status) { case '400': // 已完成 return 'gantt_success'; case '100': // 未开始 return 'gantt_begined'; case '200': // 进行中 return 'gantt_primary'; case '300': // 暂停 return 'gantt_warning'; default: // 已终止 500 return 'gantt_info'; } };
复制
然后在css内定义样式就好啦
<style lang="less" scoped> /deep/ .gantt_success .gantt_task_progress { background: #13C400 !important; border: none !important; } /deep/ .gantt_primary .gantt_task_progress { background: #3A84FF!important; border: none !important; } /deep/ .gantt_begined .gantt_task_progress { background: #9a9a9a !important; border: none !important; } /deep/ .gantt_info .gantt_task_progress { background: #FE0000 !important; border: none !important; } /deep/ .gantt_warning .gantt_task_progress { background: #FF7700 !important; border: none !important; } </style>
复制
自动延长时间刻度
gantt.config.fit_tasks = true;
复制
允许拖放
gantt.config.drag_project = true;
复制
定义x轴时间维度
做视图切换
// 年 格式 gantt.config.scales = [{ unit: 'year', step: 1, date: ' %Y 年' }]; // 月 格式 gantt.config.scales = [{ unit: 'year', step: 1, date: ' %Y 年' }, { unit: 'month', step: 1, date: '%F' }]; // 日 格式 gantt.config.scales = [{ unit: 'month', step: 1, date: ' %Y 年 %F' }, { unit: 'day', step: 1, date: '%d' }];
复制
自动调整坐标轴
当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度
gantt.config.fit_tasks = true;
复制
启用 tooltip 功能
gantt.plugins({ tooltip: true // 启用 tooltip 插件 }); gantt.templates.tooltip_text = (start, end, task) => { };
复制
性能提升
// 仅仅渲染在屏幕可见的那部分时间轴。在处理时间轴非常长的时候,可以提升性能 gantt.config.smart_scales = true // 按需渲染, 仅仅渲染在屏幕可见的那部分任务和依赖线。这个在显示大量的任务时,性能比较高。 gantt.config.smart_rendering = true
复制
增加事件
事件很多,具体看官方文档,我这里加了双击事件
// 给每行增加双击事件 ,亲测事件会重复注册,用这个方法拦截一下 if (this.onTaskDblClick) gantt.detachEvent(this.onTaskDblClick); // 双击bar任务事件(单击会有问题,点击展开时也会触发) this.onTaskDblClick = gantt.attachEvent("onTaskDblClick", (id, e) => { this.$emit('rowDbClick',id) return true; }, { id: 'onTaskDblClick' })
复制
五、完整代码
ganttPerson.vue
<template> <div> <div ref="gantt" :style="'height:' + (tabheight - 80) + 'px'" /> </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 { name: 'ganttPerson', props: ['ganttData', 'dateType'], watch: { ganttData: { handler(val) { this.tasks = { data: val } this.init(); }, deep: true } }, mounted() { let h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; this.tabheight = h - 170; if (this.height) { this.tabheight = this.height; } }, // mixins: [JeecgListMixin], data() { return { // 注册事件拦截 onTaskDblClick: null, // 甘特图配置 tasks: { data: [ // 把父节点的开始结束设置为同一天,就可以实现隐藏父节点的bar // # 字段解释 // id: 数据id 必须是唯一值,父子也不能重复 // text: 会显示在bar上的字段,如不显示就设为 '' // progress: 完成度, 0 - 1 // start_date: 开始的日期,格式在js里设置, // end_date: 结束的日期 要时分秒! 只给日期会视为日期的 00:00:00 要特殊处理一下!! // open: 如果是父节点,是否默认展开 // parent: 子节点必须有,设置为父节点的id,会自动处理,数据顺序无所谓 // #================================================================= ] // #字段解释 // 格式 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", }, tabheight: 0 }; }, methods: { // 初始化 init() { gantt.i18n.setLocale('cn'); // 汉化 - 默认是英文 // 格式化日期 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: '年' }; //自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务 gantt.config.autosize = false; //只读模式 gantt.config.readonly = true; //是否显示左侧树表格 gantt.config.show_grid = true; // 设置表头高度 gantt.config.scale_height = 50; // 设置bar的高度 gantt.config.bar_height = 26; // 设置行的高度 gantt.config.row_height = 32; // 设置时间识别格式 gantt.config.xml_date = "%Y-%m-%d %H:%i" // //表格列设置 gantt.config.columns = [ { name: 'text', label: '项目名称', tree: true, width: '200', align: 'left', template: (task)=>{ if(task.parent) { return task.text } else { return `<div style="font-weight: 700">${task.text}</div>` } }}, { name: 'person', label: '项目成员', width: '100', align: 'center' }, // { name: 'post', label: '岗位名称', width: '100', align: 'center' }, // { name: 'department', label: '部门名称', width: '100', align: 'center' }, { name: 'task', label: '项目任务', width: '100', 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" }, ]; // 为每个bar增加class gantt.templates.task_class = function(start, end, item) { switch (item.status) { case '400': // 已完成 return 'gantt_success'; case '100': // 未开始 return 'gantt_begined'; case '200': // 进行中 return 'gantt_primary'; case '300': // 暂停 return 'gantt_warning'; default: // 已终止 500 return 'gantt_info'; } }; // 自动延长时间刻度 gantt.config.fit_tasks = true; // 允许拖放 gantt.config.drag_project = true; // 定义时间格式 if(this.dateType === 'year') { // 年 格式 gantt.config.scales = [{ unit: 'year', step: 1, date: ' %Y 年' }]; } else if(this.dateType === 'month') { // 月 格式 gantt.config.scales = [{ unit: 'year', step: 1, date: ' %Y 年' }, { unit: 'month', step: 1, date: '%F' }]; } else { // 日 格式 gantt.config.scales = [{ unit: 'month', step: 1, date: ' %Y 年 %F' }, { unit: 'day', step: 1, date: '%d' }]; } // //当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' } ]; // 给每行增加双击事件 ,亲测事件会重复注册,用这个方法拦截一下 if (this.onTaskDblClick) gantt.detachEvent(this.onTaskDblClick); // 双击bar任务事件(单击会有问题,点击展开时也会触发) this.onTaskDblClick = gantt.attachEvent("onTaskDblClick", (id, e) => { this.$emit('rowDbClick',id) return true; }, { id: 'onTaskDblClick' }) // 清空旧数据 gantt.clearAll(); // 销毁gantt实例 按需开启 // gantt.destructor() // 初始化 gantt.init(this.$refs.gantt); // 数据解析 gantt.parse(this.tasks); }, } }; </script> <style lang="less" scoped> /deep/ .gantt_row.gantt_row_project:hover { background: #e4e4e4 !important; } /deep/ .gantt_row.gantt_row_task:hover { background: #e4e4e4 !important; } /deep/ .gantt_selected { background: #ececec !important; } /deep/ .gantt_task_row.gantt_selected .gantt_task_cell { background: #ececec !important; border-right-color: #ebebeb !important; } /deep/ .gantt_grid_head_cell { background-color: #f7f7f7; font-weight: 700; font-size: 13px; color: #000000; } /deep/ .gantt_scale_cell { background-color: #f7f7f7; font-weight: 700; color: #000000 !important; border-bottom: 1px solid #ebebeb; } /deep/ .gantt_task_line { border: none !important; box-shadow: none !important; } /deep/ .gantt_task_progress_wrapper { border: none !important; background-color: #E1E1E1; border-radius: 8px; } /deep/ .gantt_task_content { } /deep/ .gantt_task_line { border: none; border-radius: 8px; background-color: transparent; } /deep/ .gantt_success .gantt_task_progress { background: #13C400 !important; border: none !important; } /deep/ .gantt_primary .gantt_task_progress { background: #3A84FF!important; border: none !important; } /deep/ .gantt_begined .gantt_task_progress { background: #9a9a9a !important; border: none !important; } /deep/ .gantt_info .gantt_task_progress { background: #FE0000 !important; border: none !important; } /deep/ .gantt_warning .gantt_task_progress { background: #FF7700 !important; border: none !important; } </style>
复制
业务代码:
<template> <div style="padding: 10px"> <more-search :searchdata="searchdata" :searchform="searchform" @submit="submit" :needChangeCard="true"></more-search> <!-- 甘特图组件 --> <div style="padding: 10px;background-color: #fff;"> <gantt v-loading="tableLoading" :ganttData="ganttData" :dateType="searchform.DataType" @rowDbClick="ganttDbClick"></gantt> <div style="margin-top: 10px;text-align: right;"> <el-pagination @current-change="handleCurrentChange" @size-change="handleSizeChange" :current-page="page" background layout="total, sizes,prev, pager, next" :page-size="pageSize" :total="total" :page-sizes="[30, 50, 100, 200]"> </el-pagination> </div> </div> <!-- 详情弹窗 --> <el-drawer title="任务详情" :visible.sync="leftDialogVisible" direction="rtl"> <div style="padding: 20px;border-top: 1px #ccc solid;"> <div style="display: flex;flex-wrap: wrap;"> <div v-for="propItem in detailProp" :style="propItem.width > 200 ? 'width:100%' : 'width: 50%'" :key="propItem.prop" class="text item"> <div style="width: 110px;text-align: center;color:#94999F; border: 1px #EBEEF5 solid;flex-shrink: 0;padding: 5px;background-color: #FAFAFA;padding-left: 10px; display: flex;align-items: center;"> {{ propItem.label }} </div> <div style="border: 1px #EBEEF5 solid;padding: 5px 0 5px 10px;overflow: hidden;width: 100%;"> <div class="wordhidden"> <span v-if="propItem.formatter"> <div v-html="propItem.formatter(detailData[propItem.prop])"></div> </span> <span v-else>{{ detailData[propItem.prop] }}</span> </div> </div> </div> </div> </div> </el-drawer> </div> </template> <script> import moreSearch from '@/components/moreSearch.vue'; import gantt from '@/components/ganttPerson.vue'; import { GetList, GetUsers, GetAllDepts, GetAllPosts, GetProjectList } from '@/api/personUtilSituation.js'; export default { components: { moreSearch, gantt }, data() { return { tableLoading: false, page: 1, total: 0, pageSize: 30, leftDialogVisible: false, detailData: {}, detailProp: [ { label: '任务名称', prop: 'text', width: 300 }, { label: '项目名称', prop: 'project', width: 300 }, { label: '项目成员', prop: 'personName', width: 300 }, { label: '成员部门', prop: 'departmentName', width: 300 }, { label: '成员岗位', prop: 'postName', width: 300 }, { label: '开始日期', prop: 'start_date', width: 300, formatter: (val) => { return `<div>${ this.formatDate(val) }</div>` } }, { label: '结束日期', prop: 'end_date', width: 300, formatter: (val) => { return `<div>${ this.formatDate(val) }</div>` } }, { label: '任务状态', prop: 'status', width: 300, formatter: (val) => { switch (val) { case '400': // 已完成 return `<div style="color: #13C400; font-weight: 700;">已完成</div>`; case '100': // 未开始 return `<div style="color: #9a9a9a; font-weight: 700;">未开始</div>`; case '200': // 进行中 return `<div style="color: #3A84FF; font-weight: 700;">进行中</div>`; case '300': // 暂停 return `<div style="color: #FF7700; font-weight: 700;">暂停</div>`; default: // 已终止 500 return `<div style="color: #FE0000; font-weight: 700;">已终止</div>`; } } } ], ganttData: [], searchdata: [ { label: '展示形式', type: 'select', key: 'DataType', shortcut: true, options: [ { label: '年', value: 'year' }, { label: '月', value: 'month' }, { label: '日', value: 'day' } ] // namei18n: 'CommercialQuotationNumber', }, { label: '日期范围', type: 'datepicker', options: [], key: 'Date', shortcut: true }, { label: '项目名称', type: 'select', key: 'ProjectId', shortcut: true, options: [] // namei18n: 'CommercialQuotationNumber', }, { label: '项目成员', type: 'select', key: 'PersonId', shortcut: false, options: [] // namei18n: 'CommercialQuotationNumber', }, { label: '岗位名称', type: 'select', key: 'PostName', shortcut: false, options: [] // namei18n: 'CommercialQuotationNumber', }, { label: '部门名称', type: 'select', key: 'DepartmentName', shortcut: false, options: [] // namei18n: 'CommercialQuotationNumber', } ], searchform: { DataType: 'day', Date: [], ProjectId: '', PersonId: '', PostName: '', DepartmentName: '' }, page: 1 }; }, mounted() { this.getSelectList(); this.getList(); }, methods: { ganttDbClick(id) { console.log('接收到', id); let clickRow = this.ganttData.filter((item) => { return item.id === id; }); console.log('点击了', clickRow); this.detailData = clickRow[0]; if(!this.detailData.project) return this.leftDialogVisible = true; }, submit(val) { this.searchform = val; this.page = 1; this.getList(); }, getList() { this.tableLoading = true this.ganttData = []; let para = { Start: this.searchform.Date ? this.searchform.Date[0] : '', End: this.searchform.Date ? this.searchform.Date[1] : '', ProjectId: this.searchform.ProjectId, PersonId: this.searchform.PersonId, PostName: this.searchform.PostName, SkipCount: (this.page -1) * this.pageSize, MaxResultCount: this.pageSize }; GetList(para).then((res) => { this.total = res.response.totalCount; let data = res.response.items; let arr = []; data.forEach((item) => { // 父节点 arr.push({ id: item.id, text: item.projectName, // 第一项 项目名称 task: item.finishedCount + ' / ' + item.totalCount, // 项目任务数字 start_date: item.tasks[0].planStartDate + ' 00:00', end_date: item.tasks[0].planStartDate + ' 00:00', progress: 1, open: true, person: item.personName }); // 子节点 if (item.tasks) { item.tasks.forEach((task) => { arr.push({ id: task.id, text: task.taskName, start_date: task.planStartDate + ' 00:00', end_date: task.planFinishDate + ' 23:59', progress: 1, parent: item.id, status: task.status, project: item.projectName, departmentName: item.departmentName, personName: item.personName, postName: item.postName }); }); } }); this.ganttData = arr; this.tableLoading = false }).catch(rej=>{ this.tableLoading = false }); }, handleCurrentChange(val) { this.page = val this.getList() }, handleSizeChange(val) { this.page = 1 this.pageSize = val this.getList() }, getSelectList() { GetUsers().then((res) => { this.searchdata.forEach((item) => { if (item.key === 'PersonId') { item.options = res.response.map((item) => { return { value: item.id, label: item.name }; }); } }); }); GetAllDepts().then((res) => { this.searchdata.forEach((item) => { if (item.key === 'DepartmentName') { item.options = res.response.map((item) => { return { value: item.id, label: item.name }; }); } }); }); GetAllPosts().then((res) => { this.searchdata.forEach((item) => { if (item.key === 'PostName') { item.options = res.response.map((item) => { return { value: item.id, label: item.name }; }); } }); }); GetProjectList().then((res) => { this.searchdata.forEach((item) => { if (item.key === 'ProjectId') { item.options = res.response.map((item) => { return { value: item.id, label: item.projectName }; }); } }); }); }, formatDate(date) { if (!date) return ''; const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); // const hours = String(date.getHours()).padStart(2, '0'); // const minutes = String(date.getMinutes()).padStart(2, '0'); // const seconds = String(date.getSeconds()).padStart(2, '0'); return `${year}-${month}-${day}`; } } }; </script> <style scoped> .text { font-size: 13px; } .item { display: flex; } </style>
复制