vue前端项目实现 dhtmlxgantt 甘特图

最近项目中刚好使用了甘特图,第一次使用,在此记录一下,有需要的同学可以借鉴一下。

首先来个效果图吧,哈哈哈~~~

 因为这里用到了dhtmlx这个甘特图的组件,有些功能要专业版才能使用,但是免费的基本上符合需求了

插件文档地址:https://docs.dhtmlx.com/gantt/api__refs__gantt.html

 

 

代码如下:

  1 <template>
  2     <div class="container">
  3         <div class="select-wrap">
  4             <el-select v-model="value" placeholder="请选择" @change="selectChange">
  5                 <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
  6                 </el-option>
  7             </el-select>
  8         </div>
  9         <div ref="gantt" class="gantt-container"></div>
 10     </div>
 11 </template>
 12 <script>
 13     import {
 14         gantt
 15     } from 'dhtmlx-gantt';
 16     import "dhtmlx-gantt/codebase/dhtmlxgantt.css"
 17 
 18     export default {
 19         name: 'gantt',
 20         data() {
 21             return {
 22                 tasks: {
 23                     data: []
 24                 },
 25                 options: [{
 26                     value: '1',
 27                     label: '全部'
 28                 }, {
 29                     value: '2',
 30                     label: '完成'
 31                 }, {
 32                     value: '3',
 33                     label: '正常'
 34                 }, {
 35                     value: '4',
 36                     label: '异常'
 37                 }, {
 38                     value: '5',
 39                     label: '未启动'
 40                 }],
 41                 value: '1'
 42             }
 43         },
 44         methods: {
 45             //开始时间-结束时间参数
 46             DateDifference: function(strDateStart, strDateEnd) {
 47                 var begintime_ms = Date.parse(new Date(strDateStart.replace(/-/g, '/'))) //begintime 为开始时间
 48                 var endtime_ms = Date.parse(new Date(strDateEnd.replace(/-/g, '/'))) // endtime 为结束时间
 49                 var date3 = endtime_ms - begintime_ms //时间差的毫秒数
 50                 var days = Math.floor(date3 / (24 * 3600 * 1000))
 51                 return days
 52             },
 53             initData: function() {
 54                 this.tasks.data = [{
 55                         id: 1,
 56                         text: '概念设计',
 57                         start_date: '2020-04-08',
 58                         duration: 10,
 59                         open: true, //默认打开,
 60                         toolTipsTxt: 'xxx项目概念设计',
 61                         progress: 0.6,
 62                         status: "parent"
 63                     },
 64                     {
 65                         toolTipsTxt: 'xxx项目-项目启动会',
 66                         text: '项目启动会-外部', // 任务名
 67                         start_date: '2020-04-08', // 开始时间
 68                         id: 11, // 任务id
 69                         duration: 3, // 任务时长,从start_date开始计算
 70                         parent: 1, // 父任务ID
 71                         type: 1,
 72                         progress: 0.5,
 73                         status: "yellow"
 74                     },
 75                     {
 76                         toolTipsTxt: 'xxx项目-项目启动会议',
 77                         text: '项目启动会-内部',
 78                         start_date: '2020-04-11', 
 79                         id: 12,
 80                         duration: 2, 
 81                         parent: 1, 
 82                         type: 2,
 83                         progress: 0.6,
 84                         status: "pink"
 85                     },
 86                     {
 87                         toolTipsTxt: 'xxx项目开工会',
 88                         text: '项目开工会',
 89                         start_date: '2020-04-13', 
 90                         id: 13, 
 91                         duration: 4,
 92                         parent: 1,
 93                         type: 3,
 94                         progress: 1,
 95                         status: "green"
 96 
 97                     }, {
 98                         toolTipsTxt: 'xxx项目-项目分析',
 99                         text: '项目分析',
100                         start_date: '2020-04-13',
101                         id: 14, 
102                         duration: 4, 
103                         parent: 1,
104                         type: 4,
105                         progress: 0.6,
106                         status: "popular"
107                     },
108 
109                     {
110                         id: 2,
111                         text: '方案设计',
112                         start_date: '2020-04-08',
113                         duration: 8,
114                         open: true,
115                         toolTipsTxt: 'xxx方案设计',
116                         state: 'default',
117                         // color:"#409EFF", //设置颜色
118                         progress: 0.6,
119                         status: "parent"
120                     },
121                     {
122                         toolTipsTxt: 'xxx新项目原型图设计',
123                         text: '原型图设计', 
124                         start_date: '2020-04-08', 
125                         id: 21, 
126                         duration: 2, 
127                         parent: 2, 
128                         type: 1,
129                         progress: 0.6,
130                         status: "yellow"
131                     },
132                     {
133                         toolTipsTxt: 'xxx项目-项目设计图',
134                         text: '设计图设计',
135                         start_date: '2020-04-09', 
136                         id: 22, 
137                         duration: 2, 
138                         parent: 2,
139                         type: 2,
140                         progress: 0.6,
141                         status: "pink"
142                     },
143                     {
144                         toolTipsTxt: 'xxx项目-项目确认',
145                         text: '项目确认',
146                         start_date: '2020-04-11', 
147                         id: 23, 
148                         duration: 2, 
149                         parent: 2, 
150                         type: 3,
151                         progress: 1,
152                         status: "green"
153                     }
154 
155                 ].map(function(current, ind, arry) {
156                     var newObj = {}
157                     if (current.type) { //存在type字段 说明非一级菜单,判断阶段的具体类型 设置不同颜色
158                         if (current.type == 1) { //冒烟
159                             newObj = Object.assign({}, current, {
160                                 'color': '#fcca02'
161                             })
162                         } else if (current.type == 2) { //单元
163                             newObj = Object.assign({}, current, {
164                                 'color': '#fec0dc'
165                             })
166                         } else if (current.type == 3) { //回归
167                             newObj = Object.assign({}, current, {
168                                 'color': '#62ddd4'
169                             })
170                         } else if (current.type == 4) {
171                             newObj = Object.assign({}, current, {
172                                 'color': '#d1a6ff'
173                             })
174                         }
175                     } else { //一级菜单是蓝色的
176                         newObj = Object.assign({}, current, {
177                             'color': '#5692f0'
178                         })
179                     }
180 
181                     return newObj
182                 })
183             },
184             selectChange(val){
185                 console.log(val)
186                 
187                 //测试用例
188                 var obj = {
189                         toolTipsTxt: '新增任务',
190                         text: '新增任务', // 任务名
191                         start_date: '2020-04-15', // 开始时间
192                         id: 24, // 任务id
193                         duration: 2, // 任务时长,从start_date开始计算
194                         parent: 2, // 父任务ID
195                         type: 4,
196                         progress:0,
197                         status: "popular"
198                 }
199                 this.tasks.data.push(obj)
200 
201                 // 数据解析
202                 gantt.parse(this.tasks)
203                 // 刷新数据
204                 gantt.refreshData();
205             }
206         },
207         mounted() {
208             this.initData()
209 
210 
211             //自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务
212             gantt.config.autosize = true
213             //只读模式
214             gantt.config.readonly = true
215             //是否显示左侧树表格
216             gantt.config.show_grid = true
217             //表格列设置
218             gantt.config.columns = [{
219                     name: 'text',
220                     label: '阶段名字',
221                     tree: true,
222                     width: '280',
223                     onrender: function(task, node) {
224                         node.setAttribute("class", "gantt_cell gantt_last_cell gantt_cell_tree " + task.status);
225                     }
226                 },
227                 {
228                     name: 'duration',
229                     label: '时长',
230                     align: 'center',
231                     template: function(obj) {
232                         return obj.duration + '天'
233                     },
234                     hide: true
235                 }
236             ]
237 
238 
239 
240             var weekScaleTemplate = function(date) {
241                 var dateToStr = gantt.date.date_to_str("%m %d");
242                 var endDate = gantt.date.add(gantt.date.add(date, 1, "week"), -1, "day");
243                 var weekNum = gantt.date.date_to_str("第 %W 周");
244                 return weekNum(date)
245             };
246             var daysStyle = function(date) {
247                 var dateToStr = gantt.date.date_to_str("%D");
248                 if (dateToStr(date) == "六" || dateToStr(date) == "日") return "weekend";
249                 return "";
250             };
251             gantt.config.subscales = [{
252                     unit: "week",
253                     step: 1,
254                     template: weekScaleTemplate
255                 },
256                 {
257                     unit: "day",
258                     step: 1,
259                     format: "%d"
260                 }
261             ];
262 
263             gantt.plugins({
264                 tooltip: true
265             });
266             gantt.attachEvent("onGanttReady", function() {
267                 var tooltips = gantt.ext.tooltips;
268                 gantt.templates.tooltip_text = function(start, end, task) {
269 
270                     return task.toolTipsTxt + "<br/>" +
271                         "阶段:" + task.text + "<br/>" +
272                         gantt.templates.tooltip_date_format(start)
273                 };
274 
275 
276             });
277 
278 
279             //设置任务条进度内容
280             gantt.templates.progress_text = function(start, end, task) {
281                 return "<div style='text-align:left;color:#fff;padding-left:20px'>" + Math.round(task.progress * 100) +
282                     "% </div>";
283             };
284 
285             //任务条显示内容
286             gantt.templates.task_text = function(start, end, task) {
287                 // return task.text + '(' + task.duration + '天)';
288                 return "<div style='text-align:center;color:#fff'>" + task.text + '(' + task.duration + '天)' +
289                     "</div>";
290             }
291 
292 
293             // gantt.templates.scale_cell_class = function(date) {
294             //     /*if(date.getDay()== 0 || date.getDay()== 6){
295             //       return "weekend";
296             //     }*/
297             //     return 'weekend'
298             // }
299 
300 
301             //任务栏周末亮色
302             /*gantt.templates.task_cell_class = function(item,date){
303               if(date.getDay()== 0 || date.getDay()== 6){
304                 return "weekend";
305               }
306             };*/
307 
308 
309             //任务条上的文字大小 以及取消border自带样式
310             gantt.templates.task_class = function(start, end, item) {
311                 return item.$level == 0 ? 'firstLevelTask' : 'secondLevelTask'
312             }
313 
314             gantt.config.layout = {
315                 css: "gantt_container",
316                 cols: [{
317                         width: 280,
318                         min_width: 280,
319                         rows: [{
320                                 view: "grid",
321                                 scrollX: "gridScroll",
322                                 scrollable: true,
323                                 scrollY: "scrollVer"
324                             },
325                             {
326                                 view: "scrollbar",
327                                 id: "gridScroll",
328                                 group: "horizontal"
329                             }
330                         ]
331                     },
332                     {
333                         resizer: true,
334                         width: 1
335                     },
336                     {
337                         rows: [{
338                                 view: "timeline",
339                                 scrollX: "scrollHor",
340                                 scrollY: "scrollVer"
341                             },
342                             {
343                                 view: "scrollbar",
344                                 id: "scrollHor",
345                                 group: "horizontal"
346                             }
347                         ]
348                     },
349                     {
350                         view: "scrollbar",
351                         id: "scrollVer"
352                     }
353                 ]
354             };
355 
356             //时间轴图表中,任务条形图的高度
357             // gantt.config.task_height = 28            
358             //时间轴图表中,甘特图的高度
359             // gantt.config.row_height = 36            
360             //时间轴图表中,如果不设置,只有行边框,区分上下的任务,设置之后带有列的边框,整个时间轴变成格子状。
361             gantt.config.show_task_cells = true
362             //当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度
363             gantt.config.fit_tasks = true
364             gantt.config.min_column_width = 50;
365             gantt.config.auto_types = true;
366             gantt.config.xml_date = "%Y-%m-%d";
367             gantt.config.scale_unit = "month";
368             gantt.config.step = 1;
369             gantt.config.date_scale = "%Y年%M";
370             gantt.config.start_on_monday = true;
371             gantt.config.scale_height = 90;
372             gantt.config.autoscroll = true;
373             gantt.config.calendar_property = "start_date";
374             gantt.config.calendar_property = "end_date";
375             gantt.config.readonly = true;
376             gantt.i18n.setLocale('cn');
377 
378             // 初始化
379             gantt.init(this.$refs.gantt)
380             // 数据解析
381             gantt.parse(this.tasks)
382         }
383     }
384 </script>
385 <style lang="scss">
386     .firstLevelTask {
387         border: none;
388 
389         .gantt_task_content {
390             font-size: 13px;
391         }
392     }
393 
394     .secondLevelTask {
395         border: none;
396     }
397 
398     .thirdLevelTask {
399         border: 2px solid #da645d;
400         color: #da645d;
401         background: #da645d;
402     }
403 
404     .milestone-default {
405         border: none;
406         background: rgba(0, 0, 0, 0.45);
407     }
408 
409     .milestone-unfinished {
410         border: none;
411         background: #5692f0;
412     }
413 
414     .milestone-finished {
415         border: none;
416         background: #84bd54;
417     }
418 
419     .milestone-canceled {
420         border: none;
421         background: #da645d;
422     }
423 
424     html,
425     body {
426         margin: 0px;
427         padding: 0px;
428         height: 100%;
429         overflow: hidden;
430     }
431 
432     .container {
433         height: 100%;
434         width: 100%;
435         position: relative;
436         .gantt_grid_head_cell {
437             padding-left: 20px;
438             text-align: left !important;
439             font-size: 14px;
440             color: #333;
441         }
442 
443         .select-wrap {
444             position: absolute;
445             top: 25px;
446             z-index: 99;
447             width: 90px;
448             left: 180px;
449 
450             .el-input__inner {
451                 border: none;
452             }
453         }
454 
455         .left-container {
456             height: 100%;
457         }
458 
459         .parent {
460             .gantt_tree_icon {
461                 &.gantt_folder_open {
462                     background-image: url(assets/gantt-icon.svg) !important;
463                 }
464                 &.gantt_folder_closed{
465                     background-image: url(assets/gantt-icon-up.svg) !important;
466                 }
467             }
468         }
469 
470         .green,
471         .yellow,
472         .pink,
473         .popular {
474             .gantt_tree_icon.gantt_file {
475                 background: none;
476                 position: relative;
477 
478                 &::before {
479                     content: "";
480                     width: 10px;
481                     height: 10px;
482                     border-radius: 50%;
483                     position: absolute;
484                     left: 50%;
485                     top: 50%;
486                     transform: translate(-50%, -50%);
487                 }
488             }
489         }
490 
491         .green {
492             .gantt_tree_icon.gantt_file {
493                 &::before {
494                     background: #84bd54;
495                 }
496             }
497         }
498 
499         .yellow {
500             .gantt_tree_icon.gantt_file {
501                 &::before {
502                     background: #fcca02;
503                 }
504             }
505         }
506 
507         .pink {
508             .gantt_tree_icon.gantt_file {
509                 &::before {
510                     background: #da645d;
511                 }
512             }
513         }
514 
515         .popular {
516             .gantt_tree_icon.gantt_file {
517                 &::before {
518                     background: #d1a6ff;
519                 }
520             }
521         }
522 
523     }
524 
525     .left-container {
526         height: 100%;
527     }
528 
529     .gantt_task_content {
530         text-align: left;
531         padding-left: 10px;
532     }
533 </style>

 

 

 

posted @ 2021-11-26 16:06  秃头的铲屎官  Views(6670)  Comments(0Edit  收藏  举报