瀏覽代碼

甘特图调整

fujunwen 4 年之前
父節點
當前提交
d6f560e348

+ 61 - 41
src/utils/ganttChart/GanttChart.js

@@ -1,5 +1,4 @@
 import moment from 'moment';
-// import './g.js';
 /**
  * 数据定义区域
  *
@@ -10,7 +9,7 @@ import moment from 'moment';
  */
 export function GanttChart(options) {
   // 任务列表
-  this.tasks = [];
+  this.tasks = options.tasks || [];
   // AntVG Canvas
   this.gCanvas = null;
   // 视口宽度 800,可视区域
@@ -35,22 +34,28 @@ export function GanttChart(options) {
   // 每天的间隔宽度
   this.dayStep = 40;
   // 分组标题高度
-  this.groupTitleHeight = 30;
+  this.groupTitleHeight = 38;
   // 任务矩形高度
   this.taskRowHeight = 16;
+  // 每行任务的纵向间距
+  this.rowSpanDis = 22;
   // 总天数
   this.daysCount = options['daysCount'] || 60;
+  // 任务图距离顶部高度
+  this.graphTopDis = 20
   
   // 每像素代表的小时数
   this.timePerPix = this.cWidth/this.daysCount/24/3600
   // 当前视图开始时间,向前推N天
   this.startAt = moment().subtract(this.daysCount / 3, 'days');
   this.endAt = moment(this.startAt).add(this.daysCount, 'days');
-  this.graphDiv = document.getElementById('graphDiv');
+  this.graphDiv = document.getElementById(options['chartContainer']);
   // 图形容器组
   this.graphGroup = null;
   // 上一次拖动的事件
   this.lastDragEv = null;
+  // 回调事件
+  this.callback = options.callback || null;
 }
 
 
@@ -66,14 +71,14 @@ GanttChart.prototype.changeTasks = function(_tasks){
  * 打开关闭分组
  */
 
-GanttChart.prototype.toggle = function(no) {
-  if (tasks[no].open) {
-    tasks[no].open = false;
+GanttChart.prototype.toggle = function(index) {
+  if (this.tasks[index].open) {
+    this.tasks[index].open = false;
   } else {
-    tasks[no].open = true;
+    this.tasks[index].open = true;
   }
-  processData();
-  drawTasks();
+  this.processData();
+  this.drawTasks();
 }
 
 /**
@@ -86,15 +91,15 @@ GanttChart.prototype.processData = function() {
     currentTopTask.renderOptions = {};
     if (i != 0) {
       // 非0个,要补上前面的数据
-      lastTopTask = tasks[i - 1];
+      lastTopTask = this.tasks[i - 1];
       currentTopTask.renderOptions.startY = lastTopTask.renderOptions.endY + 20;
     } else {
       // 第一个
-      currentTopTask.renderOptions.startY = 120;
+      currentTopTask.renderOptions.startY = this.graphTopDis;
     }
     if (currentTopTask.open) {
       currentTopTask.renderOptions.endY =
-        currentTopTask.renderOptions.startY + this.groupTitleHeight + currentTopTask.dataList.length * this.taskRowHeight;
+        currentTopTask.renderOptions.startY + this.rowSpanDis + this.groupTitleHeight + currentTopTask.dataList.length * this.taskRowHeight;
     } else {
       currentTopTask.renderOptions.endY = currentTopTask.renderOptions.startY + this.groupTitleHeight;
     }
@@ -135,10 +140,10 @@ GanttChart.prototype.pageTo = function(dir = 'next') {
   } else {
     // 向前翻页
     this.startAt = this.startAt.subtract(this.daysCount, 'days');
-    this.offsetDis = 1800 //2*viewWidth
+    this.offsetDis = 2*this.viewWidth
   }
   this.endAt = moment(this.startAt).add(this.daysCount, 'days');
-  console.log('已翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'));
+  console.log('已翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'), this.offsetDis);
   // offsetDis = viewWidth;
   this.forceRefreshGraph();
 }
@@ -153,7 +158,7 @@ GanttChart.prototype.doDrag = function(sEvent, eEvent) {
   if (sEvent == null) {
     sEvent = this.startEvent;
   }
-
+  
   let sPos = sEvent.clientX;
   let cPos = eEvent.clientX;
   // 滚动距离
@@ -164,16 +169,16 @@ GanttChart.prototype.doDrag = function(sEvent, eEvent) {
   // console.log('draging...',tempDis, this.offsetDis, dis)
   if (this.offsetDis <= -20) {
     // 向前滑动,向前翻页
-    console.log('此处应该向前翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'));
+    console.log('此处应该向前翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'),this.offsetDis);
     this.offsetDis = this.viewWidth;
     this.pageTo('prev');
   }
-  if (this.offsetDis - 20 >= 1800 ){ //cWidth - viewWidth) {
+  if (this.offsetDis - 20 >= 2964 ){ //cWidth - viewWidth) {
     // 向后滑动,向后翻页
-    console.log('此处应该向后翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'));
+    console.log('此处应该向后翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'),this.offsetDis);
     this.offsetDis = this.viewWidth;
     this.pageTo('next');
-  }        
+  }
   this.graphDiv.scrollLeft = this.offsetDis;
 }
 
@@ -183,7 +188,7 @@ GanttChart.prototype.doDrag = function(sEvent, eEvent) {
 
 GanttChart.prototype.initDragHandler = function() {
   this.graphDiv.scrollLeft = this.offsetDis;
-  let _canvas = document.getElementsByTagName('canvas')[0];
+  let _canvas = document.getElementsByTagName('canvas')[1];
   _canvas.addEventListener('mousedown', (ev) => {
     this.draging = true;
     this.startEvent = ev;
@@ -200,6 +205,7 @@ GanttChart.prototype.initDragHandler = function() {
   });
 
   _canvas.addEventListener('mousemove', (ev) => {
+    // console.log('this over', this)
     if (this.draging) {
       if (new Date() - this.lastClickAt < 20) {
         return false;
@@ -209,6 +215,11 @@ GanttChart.prototype.initDragHandler = function() {
       this.lastDragEv = ev;
     }
   });
+  _canvas.addEventListener('mouseleave', (ev) => {
+    console.log('leave...恢复')
+    this.draging = false;
+    this.endEvent = ev;
+  });
 }
 /**
  * 初始化画布
@@ -218,7 +229,7 @@ GanttChart.prototype.initDragHandler = function() {
 GanttChart.prototype.initCanvas = function() {
   this.gCanvas = new G.Canvas({
     container: 'ganttContainer',
-    width: 2400,
+    width: this.cWidth,
     height: 800,
   });
 }
@@ -240,7 +251,7 @@ GanttChart.prototype.drawTimeZone = function() {
       fontSize: 12,
       text: start.format('YYYY-MM'),
       lineDash: [10, 10],
-      fill: 'red',
+      fill: '#8D9399',
     },
   });
   timeGroup.addShape('text', {
@@ -250,7 +261,7 @@ GanttChart.prototype.drawTimeZone = function() {
       fontSize: 12,
       text: start.add(this.daysCount / 3, 'days').format('YYYY-MM'),
       lineDash: [10, 10],
-      fill: 'red',
+      fill: '#8D9399',
     },
   });
   timeGroup.addShape('text', {
@@ -260,13 +271,13 @@ GanttChart.prototype.drawTimeZone = function() {
       fontSize: 12,
       text: start.add(this.daysCount / 3, 'days').format('YYYY-MM'),
       lineDash: [10, 10],
-      fill: 'red',
+      fill: '#8D9399',
     },
   });
   let startSecond = moment(this.startAt);
   // 绘制第二级
   for (let i = 0; i < this.daysCount; i++) {
-    let timeText = startSecond.add(1, 'days').format('MM-DD');
+    let timeText = startSecond.add(1, 'days').format('DD');
     timeGroup.addShape('text', {
       attrs: {
         x: 40 * i,
@@ -274,7 +285,7 @@ GanttChart.prototype.drawTimeZone = function() {
         fontSize: 10,
         text: timeText,
         lineDash: [10, 10],
-        fill: 'red',
+        fill: '#8D9399',
       },
     });
   }
@@ -284,19 +295,22 @@ GanttChart.prototype.drawTimeZone = function() {
  * 处理点击
  */
 GanttChart.prototype.handleClick = function(task, flag, ev) {
-  let detailDiv = document.getElementById('detailDiv')
+  // let detailDiv = document.getElementById('detailDiv')
   if(flag == 'enter'){
-    detailDiv.style.display = 'block'
-    detailDiv.style.left = ev.clientX+'px';
-    detailDiv.style.top = ev.clientY+'px';
-    document.getElementById('detailTaskName').textContent = task._pdata.description
-    document.getElementById('detailTaskStatus').textContent = task._pdata.status
-    document.getElementById('detailTaskStartDate').textContent = task._pdata.startDate
-    document.getElementById('detailTaskEndDate').textContent = task._pdata.endDate
+    // detailDiv.style.display = 'block'
+    // detailDiv.style.left = ev.clientX+'px';
+    // detailDiv.style.top = ev.clientY+'px';
+    // document.getElementById('detailTaskName').textContent = task._pdata.description
+    // document.getElementById('detailTaskStatus').textContent = task._pdata.status
+    // document.getElementById('detailTaskStartDate').textContent = task._pdata.startDate
+    // document.getElementById('detailTaskEndDate').textContent = task._pdata.endDate
     console.log('show:', task);
-  }else{
-    detailDiv.style.display = 'none'
+  } else if (flag === 'leave'){
+    // detailDiv.style.display = 'none'
     console.log('hide:', task);
+  } else {
+    this.callback(task);
+    console.log('click:', task);
   }
 }
 
@@ -343,25 +357,28 @@ GanttChart.prototype.drawTasks = function() {
     this.graphGroup = this.gCanvas.addGroup();
     this.graphGroup._tname = 'graphGroup';
   }
+  // 第一层循环,用于分组,例如,维保--xxxx
   this.tasks.forEach((topTask, topIndex) => {
     if (topTask.open) {
       let taskGroup = null;
       taskGroup = this.graphGroup.addGroup();
       taskGroup._tname = 'TaskGroup_' + topTask.id;
-      topTask.gGroup = taskGroup;            
+      topTask.gGroup = taskGroup;
+      // 第二层循环,用于 区分具体多少任务,例如,维保-商管1/商管2...    
       topTask.dataList.forEach((taskP, index) => {                            
-        // 在视图中才显示
         let taskPGroup = taskGroup.addGroup();
         taskGroup.addGroup(taskPGroup);
+        // 第三层循环,用户区分每个子任务的执行时间段,例如:维保-商管1-2020.05-2020.06 / 2020.08- 2020.09
         taskP.tasks.forEach((_taskItem, _index) => {
           let _isInView = this.isInView(_taskItem)
+          // 在视图中才显示
           if(_isInView){
             let pos = this.calRectPos(_taskItem);
             // console.log('render rect:', _taskItem, pos, topTask.renderOptions.startY + index * taskRowHeight);
             let rectEl = taskPGroup.addShape('rect', {
               attrs: {
                 x: pos.x,
-                y: topTask.renderOptions.startY + (index* this.taskRowHeight),
+                y: topTask.renderOptions.startY + (index* (this.taskRowHeight + this.rowSpanDis)),
                 width: pos.width,
                 height: this.taskRowHeight,
                 fill: this.statusColor(_taskItem),
@@ -376,6 +393,9 @@ GanttChart.prototype.drawTasks = function() {
             rectEl.on('mouseleave', (ev) => {
               this.handleClick(ev.target, 'leave', ev);
             });
+            rectEl.on('click', (ev) => {
+              this.handleClick(ev.target, 'click', ev);
+            });
           }
         });
       });
@@ -398,7 +418,7 @@ GanttChart.prototype.calRectPos = function(taskItem) {
   let duraStartAt = new Date(taskItem.startDate) - new Date(this.startAt.format('YYYY-MM-DD'));
   let secondsStartAt = duraStartAt/1000
 
-  let duraEndAt = new Date(taskItem.endDate) - new Date(this.startAt.format('YYYY-MM-DD'));        
+  let duraEndAt = new Date(taskItem.endDate) - new Date(taskItem.startDate);        
   let secondsEndAt = duraEndAt/1000
   return {
     x: secondsStartAt * this.timePerPix,

+ 2 - 2
src/views/analysis/CoreDeviceReport.vue

@@ -278,10 +278,10 @@ export default {
                 name = '专维'
                 break
               case '1':
-                name = '维保专业'
+                name = '维保'
                 break
               case '2':
-                name = '第三方视图'
+                name = '第三方检测'
                 break
             }
             item.typeName = name;

+ 57 - 12
src/views/analysis/GanttChart.vue

@@ -29,11 +29,14 @@
     <div class="main-gantt-container">
       <div class="task-title">
         <div class="title">任务标题</div>
-        <Tree :data="treeData" />
+        <Tree :data="treeData" @openNode="toggleNode" />
       </div>
-      <div class="chart-container">
+      <div class="chart-container" id="chartContainer" ref="chartContainer">
         <div id="ganttContainer"></div>
       </div>
+      <el-dialog :title="detailTitle" :visible.sync="showDetail" width="840px">
+
+      </el-dialog>
     </div>
   </div>
 </template>
@@ -46,6 +49,7 @@ import _ from 'lodash';
 import moment from 'moment';
 // import '../../utils/ganttChart/g.js';
 import { GanttChart } from '../../utils/ganttChart/GanttChart.js';
+import { parse } from 'path';
 export default {
   data () {
     return {
@@ -54,11 +58,15 @@ export default {
       legends: [
         {id: 1, text: '按时完成', backgroundColor: '#E7E9EA', borderColor: '#C3C7CB'},
         {id: 2, text: '未开始/进行中', backgroundColor: 'rgba(91, 143, 249, 0.2)', borderColor: '#5B8FF9'},
-        {id: 3, text: '按时完成', backgroundColor: '#FBCE99', borderColor: '#F58300'},
-        {id: 4, text: '按时完成', backgroundColor: '#FBB8B5', borderColor: '#F54E45'},
+        {id: 3, text: '逾期完成', backgroundColor: '#FBCE99', borderColor: '#F58300'},
+        {id: 4, text: '逾期未完成', backgroundColor: '#FBB8B5', borderColor: '#F54E45'},
       ], // 图例
       timeType: 'month', // 甘特图时间类型
       treeData: [], // 树结构数据
+      
+      // 弹窗相关
+      showDetail: false, // 弹框显示状态
+      detailTitle: '', // 弹窗标题
     }
   },
 
@@ -134,17 +142,36 @@ export default {
             newData.push({
               id: index + 1,
               name: name[index],
-              open: false,
-              children: this.disGanttData(item)
+              open: true,
+              children: name[index] === '专维'?[] : this.disGanttData(dsfList)
             })
           })
-          console.log('newData', newData)
+          
           this.treeData = newData;
-          console.log('GanttChart', GanttChart)
+          
+          let taskData = _.map(_.cloneDeep(newData), (item) => {
+            return {
+              id: item.id,
+              type: item.name,
+              open: item.open,
+              dataList: _.map(item.children, (_item) => {
+                return {
+                  id: _item.id,
+                  title: _item.name,
+                  tasks: _item.originData
+                }
+              })
+            }
+          })
+          console.log('taskData', taskData)
+          let width = this.$refs.chartContainer.offsetWidth;
           window.gc = new GanttChart({
-            viewWidth: 800,
-            cWidth: 2400,
-            tasks: newData
+            viewWidth: width,
+            cWidth: 3*width,
+            tasks: taskData,
+            chartContainer: 'chartContainer',
+            daysCount: parseInt(3*width/40),
+            callback: this.showDialog
           });
           gc.main()
         }
@@ -160,10 +187,28 @@ export default {
           id: item.id,
           name: item.name,
           checked: 'uncheck',
-          originData: item.data[0]
+          originData: _.map(item.data, (_item) => {
+            _item.startDate = moment.unix((new Date().getTime() - 1000*60*60*24*7)/1000).format('YYYY-MM-DD HH:mm:ss');
+            _item.endDate = moment.unix(new Date().getTime()/1000).format('YYYY-MM-DD HH:mm:ss');
+            _item.description = _item.parentname;
+            return _item
+          })
         })
       })
       return data
+    },
+    /**
+     * 展开收起节点
+     */
+    toggleNode(status) {
+      console.log('status', status)
+    },
+    /**
+     * 显示弹窗
+     */
+    showDialog(task) {
+      this.showDetail = true;
+      this.detailTitle = task._pdata.description;
     }
   }
 }

+ 3 - 3
src/views/analysis/SpecificationUpdateRecord.vue

@@ -51,9 +51,9 @@ export default {
     return {
       incidentList: [
         {id: 0, name: '专维'},
-        {id: 1, name: '维保任务'},
-        {id: 2, name: '第三方视图'},
-        {id: 3, name: '综合事项'},
+        {id: 1, name: '维保'},
+        {id: 2, name: '第三方检测'},
+        {id: 3, name: '重点关注'},
       ], // 事件列表
       incidentType: '', // 事件类型
       timeVal: '', // 时间

File diff suppressed because it is too large
+ 26486 - 0
static/g.js