فهرست منبع

甘特图调整

fujunwen 4 سال پیش
والد
کامیت
559a8e6dbd

+ 153 - 60
src/utils/ganttChart/GanttChart.js

@@ -1,9 +1,5 @@
 import moment from 'moment';
 /**
- * 数据定义区域
- *
- */
-/**
  * 甘特图
  * @param {} options 
  */
@@ -28,7 +24,7 @@ export function GanttChart(options) {
   // 拖动过程事件
   this.dragingEvent = null;
   // 拖动偏移量
-  this.offsetDis = options['viewWidth'] || 800;
+  this.offsetDis = (options['viewWidth']/2) || 800;
   // 拖动定时器
   this.dragTimer = null;
   // 每天的间隔宽度
@@ -42,20 +38,21 @@ export function GanttChart(options) {
   // 总天数
   this.daysCount = options['daysCount'] || 60;
   // 任务图距离顶部高度
-  this.graphTopDis = 20
+  this.graphTopDis = 40
   
   // 每像素代表的小时数
   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(options['chartContainer']);
+  this.graphDiv = document.getElementById(options['chartParentContainer']);
+  this.chartContainer = options['chartContainer']
   // 图形容器组
   this.graphGroup = null;
   // 上一次拖动的事件
   this.lastDragEv = null;
-  // 回调事件
-  this.callback = options.callback || null;
+  // 当日刻度线
+  this.todayTimeLineEl = null;
 }
 
 
@@ -113,6 +110,7 @@ GanttChart.prototype.forceRefreshGraph = function() {
   this.tasks.forEach((topTask) => {
     topTask.gGroup = null;
   });
+  this.todayTimeLineEl = null
   this.gCanvas.destroy();
   this.initDrawingReady();
 }
@@ -122,17 +120,21 @@ GanttChart.prototype.forceRefreshGraph = function() {
  */
 GanttChart.prototype.initDrawingReady = function() {
   this.initCanvas();
-  this.initDragHandler();
-  this.drawTimeZone();
-  this.processData();
-  this.drawTasks();
-  this.graphGroup = null
+  setTimeout(() => {
+    this.initDragHandler();
+    this.drawTimeZone();
+    this.processData();
+    this.drawTasks();
+    this.graphGroup = null
+  }, 200);
 }
 
 /**
  * 翻页
  */
 GanttChart.prototype.pageTo = function(dir = 'next') {
+  this.draging = false;
+  this.endEvent = null;
   if (dir == 'next') {
     // 向后翻页`
     this.startAt = this.startAt.add(this.daysCount, 'days');
@@ -154,7 +156,7 @@ let lastClickAt = null;
  * 改变graphDiv 滚动距离
  * 到达边界距离后,刷新页面
  */
-GanttChart.prototype.doDrag = function(sEvent, eEvent) {
+GanttChart.prototype.doDrag = function(sEvent, eEvent) {  
   if (sEvent == null) {
     sEvent = this.startEvent;
   }
@@ -173,7 +175,7 @@ GanttChart.prototype.doDrag = function(sEvent, eEvent) {
     this.offsetDis = this.viewWidth;
     this.pageTo('prev');
   }
-  if (this.offsetDis - 20 >= 2964 ){ //cWidth - viewWidth) {
+  if ((this.offsetDis - 20) >= this.viewWidth*2.2 ){ //cWidth - viewWidth) {
     // 向后滑动,向后翻页
     console.log('此处应该向后翻页', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'),this.offsetDis);
     this.offsetDis = this.viewWidth;
@@ -185,10 +187,9 @@ GanttChart.prototype.doDrag = function(sEvent, eEvent) {
 /**
  * 初始化抓取拖动事件
  */
-
 GanttChart.prototype.initDragHandler = function() {
   this.graphDiv.scrollLeft = this.offsetDis;
-  let _canvas = document.querySelector('#ganttContainer>canvas');
+  let _canvas = this._canvas
   _canvas.addEventListener('mousedown', (ev) => {
     this.draging = true;
     this.startEvent = ev;
@@ -199,6 +200,13 @@ GanttChart.prototype.initDragHandler = function() {
     this.lastDragEv = ev;
   });
 
+
+  _canvas.addEventListener('mouseleave', (ev) => {
+    console.log('leave...恢复')
+    this.draging = false;
+    this.endEvent = ev;
+  });
+
   _canvas.addEventListener('mouseup', (ev) => {
     this.draging = false;
     this.endEvent = ev;
@@ -215,11 +223,6 @@ GanttChart.prototype.initDragHandler = function() {
       this.lastDragEv = ev;
     }
   });
-  _canvas.addEventListener('mouseleave', (ev) => {
-    console.log('leave...恢复')
-    this.draging = false;
-    this.endEvent = ev;
-  });
 }
 /**
  * 初始化画布
@@ -227,11 +230,13 @@ GanttChart.prototype.initDragHandler = function() {
  */
 
 GanttChart.prototype.initCanvas = function() {
+  console.error('初始化画布...')
   this.gCanvas = new G.Canvas({
-    container: 'ganttContainer',
+    container: this.chartContainer,
     width: this.cWidth,
-    height: 800,
+    height: this.cHeight,
   });
+  this._canvas = document.getElementsByTagName('canvas')[0];
 }
 
 /**
@@ -242,45 +247,59 @@ GanttChart.prototype.drawTimeZone = function() {
   console.log('时间段', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'));
   let start = moment(this.startAt);
   let timeGroup = this.gCanvas.addGroup();
+  this.timeGroupEl = timeGroup
   timeGroup._tname = 'TimeGroup';
-  // 绘制第一级
-  timeGroup.addShape('text', {
-    attrs: {
-      x: 20,
-      y: 20,
-      fontSize: 12,
-      text: start.format('YYYY-MM'),
-      lineDash: [10, 10],
-      fill: '#8D9399',
-    },
-  });
-  timeGroup.addShape('text', {
-    attrs: {
-      x: 20 + this.viewWidth,
-      y: 20,
-      fontSize: 12,
-      text: start.add(this.daysCount / 3, 'days').format('YYYY-MM'),
-      lineDash: [10, 10],
-      fill: '#8D9399',
-    },
-  });
-  timeGroup.addShape('text', {
+  let startSecond = moment(this.startAt);
+
+  // 顶部底部边框
+  timeGroup.addShape('rect',{
     attrs: {
-      x: 20 + this.viewWidth * 2,
-      y: 20,
-      fontSize: 12,
-      text: start.add(this.daysCount / 3, 'days').format('YYYY-MM'),
-      lineDash: [10, 10],
-      fill: '#8D9399',
+      x: 0,
+      y: 0,
+      width: this.cWidth,
+      height: 40,
+      fill: '#dbcccc',
+      radius: [2, 4],
     },
-  });
-  let startSecond = moment(this.startAt);
+  })
   // 绘制第二级
+  let nowAtStr = moment().format('YYYY-MM-DD')
   for (let i = 0; i < this.daysCount; i++) {
-    let timeText = startSecond.add(1, 'days').format('DD');
+    let tempAt = startSecond.add(1, 'days')
+    let timeText = tempAt.format('DD');
+    if(timeText == '01'){
+      // 第一天,顶部需要绘制年月
+      timeGroup.addShape('text', {
+        attrs: {
+          x: this.dayStep * i,
+          y: 20,
+          fontSize: 12,
+          text: tempAt.format('YYYY-MM'),
+          lineDash: [10, 10],
+          fill: '#8D9399',
+        },
+      });
+      
+    }
+    let isToday = nowAtStr == tempAt.format('YYYY-MM-DD')
+    if(isToday){
+      //是今日,需要画线
+      console.log('绘制 当日刻度线')
+      this.todayTimeLineOffsetPos = this.dayStep * i
+      timeGroup.addShape('rect',{
+        attrs: {
+          x: this.dayStep * i-10,
+          y: 25,
+          width: 30,
+          height: 16,
+          fill: '#0091FF',
+          radius: [2, 4],
+        },
+      })
+    }
     timeGroup.addShape('text', {
       attrs: {
-        x: 40 * i,
+        x: this.dayStep * i,
         y: 40,
         fontSize: 10,
         text: timeText,
@@ -288,6 +307,17 @@ GanttChart.prototype.drawTimeZone = function() {
         fill: '#8D9399',
       },
     });
+
+    timeGroup.addShape('rect', {
+      attrs: {
+        x: this.dayStep * i-10,
+        y: 20,
+        width: 1,
+        height: this.cHeight,
+        fill: '#deebeb',
+        radius: [2, 4],
+      },
+    });
   }
 }
 
@@ -364,10 +394,55 @@ GanttChart.prototype.drawTasks = function() {
       taskGroup = this.graphGroup.addGroup();
       taskGroup._tname = 'TaskGroup_' + topTask.id;
       topTask.gGroup = taskGroup;
-      // 第二层循环,用于 区分具体多少任务,例如,维保-商管1/商管2...    
-      topTask.dataList.forEach((taskP, index) => {                            
-        let taskPGroup = taskGroup.addGroup();
+
+      // 组名背景矩形
+      // let TopGroupRectEl = taskGroup.addShape('rect', {
+      //   attrs: {
+      //     x: 0,
+      //     y: topTask.renderOptions.startY,
+      //     width: this.cWidth,
+      //     height: this.taskRowHeight,
+      //     fill: '#a6ed53',
+      //     radius: [2, 4],
+      //   },
+      // });
+      // 第二层循环,用于 区分具体多少任务,例如,维保-商管1/商管2...
+      topTask.dataList.forEach((taskP, index) => {
+        let taskPGroup = taskGroup.addGroup()
         taskGroup.addGroup(taskPGroup);
+        // 任务背景矩形,主要用于Hover效果变更颜色
+        if(true){
+          let tempTaskContainerEl = taskPGroup.addShape('rect', {
+            attrs: {
+              x: 0,
+              y: topTask.renderOptions.startY + ((index+1)* (this.taskRowHeight + this.rowSpanDis))-5,
+              width: this.cWidth,
+              height: this.taskRowHeight+10,
+              fill: '#fff',
+              // stroke: 'black',
+              radius: [2, 4],
+            },
+          });
+          tempTaskContainerEl.setZIndex(1)
+          tempTaskContainerEl._pdata = taskP
+          tempTaskContainerEl.on('mouseenter',(ev)=>{
+            tempTaskContainerEl.attr({fill: '#F5F6F7'})
+            tempTaskContainerEl._pdata.tasks.forEach(_tempTask=>{
+              if(_tempTask._rectEl){
+                _tempTask._rectEl.setZIndex(5)
+              }
+            })
+          })
+          tempTaskContainerEl.on('mouseleave',(ev)=>{
+            tempTaskContainerEl.attr({fill: '#fff'})
+            tempTaskContainerEl._pdata.tasks.forEach(_tempTask=>{
+              if(_tempTask._rectEl){
+                _tempTask._rectEl.setZIndex(5)
+              }
+            })
+          })
+          taskP._containerEl = tempTaskContainerEl
+        }
         // 第三层循环,用户区分每个子任务的执行时间段,例如:维保-商管1-2020.05-2020.06 / 2020.08- 2020.09
         taskP.tasks.forEach((_taskItem, _index) => {
           let _isInView = this.isInView(_taskItem)
@@ -386,7 +461,9 @@ GanttChart.prototype.drawTasks = function() {
                 radius: [2, 4],
               },
             });
+            rectEl.setZIndex(5)
             rectEl._pdata = _taskItem;
+            _taskItem._rectEl = rectEl
             rectEl.on('mouseover', (ev) => {
               this.handleClick(ev.target, 'enter', ev);
             });
@@ -408,6 +485,22 @@ GanttChart.prototype.drawTasks = function() {
       }
     }
   });
+
+  // 画当前线条 TODO,放前面不行
+  let todayAt = new Date()
+  if(this.startAt < todayAt && this.endAt > todayAt){
+    this.todayTimeLineEl = this.gCanvas.addShape('rect',{
+      attrs: {
+        x: this.todayTimeLineOffsetPos,
+        y: 40,
+        width: 3,
+        height: this.cHeight,
+        fill: '#0091FF',
+        radius: [2, 4],
+      }
+    })
+    this.todayTimeLineEl.setZIndex(50)
+  }
 }
 
 /**

+ 438 - 0
src/utils/ganttChart/GanttChart_old.js

@@ -0,0 +1,438 @@
+import moment from 'moment';
+/**
+ * 数据定义区域
+ *
+ */
+/**
+ * 甘特图
+ * @param {} options 
+ */
+export function GanttChart(options) {
+  // 任务列表
+  this.tasks = options.tasks || [];
+  // AntVG Canvas
+  this.gCanvas = null;
+  // 视口宽度 800,可视区域
+  this.viewWidth = options['viewWidth'] || 800;
+  // 物理画布宽度 800
+  this.cWidth = options['cWidth'] || 2400;
+  this.cHeight = options['cHeight'] || 600;
+  // 画布偏移位置
+  this.startPos = 0;
+  // 是否拖动中
+  this.draging = false;
+  // 开始拖动事件
+  this.startEvent = null;
+  // 结束拖动事件
+  this.endEvent = null;
+  // 拖动过程事件
+  this.dragingEvent = null;
+  // 拖动偏移量
+  this.offsetDis = options['viewWidth'] || 800;
+  // 拖动定时器
+  this.dragTimer = null;
+  // 每天的间隔宽度
+  this.dayStep = 40;
+  // 分组标题高度
+  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(options['chartContainer']);
+  // 图形容器组
+  this.graphGroup = null;
+  // 上一次拖动的事件
+  this.lastDragEv = null;
+  // 回调事件
+  this.callback = options.callback || null;
+}
+
+
+/**
+ * 设置数据
+ * @param {*} _tasks 
+ */
+GanttChart.prototype.changeTasks = function(_tasks){
+  this.tasks = _tasks
+}
+
+/**
+ * 打开关闭分组
+ */
+
+GanttChart.prototype.toggle = function(index) {
+  if (this.tasks[index].open) {
+    this.tasks[index].open = false;
+  } else {
+    this.tasks[index].open = true;
+  }
+  this.processData();
+  this.drawTasks();
+}
+
+/**
+ * 预处理数据
+ */
+GanttChart.prototype.processData = function() {
+  for (let i = 0; i < this.tasks.length; i++) {
+    let currentTopTask = this.tasks[i];
+    let lastTopTask = null;
+    currentTopTask.renderOptions = {};
+    if (i != 0) {
+      // 非0个,要补上前面的数据
+      lastTopTask = this.tasks[i - 1];
+      currentTopTask.renderOptions.startY = lastTopTask.renderOptions.endY + 20;
+    } else {
+      // 第一个
+      currentTopTask.renderOptions.startY = this.graphTopDis;
+    }
+    if (currentTopTask.open) {
+      currentTopTask.renderOptions.endY =
+        currentTopTask.renderOptions.startY + this.rowSpanDis + this.groupTitleHeight + currentTopTask.dataList.length * this.taskRowHeight;
+    } else {
+      currentTopTask.renderOptions.endY = currentTopTask.renderOptions.startY + this.groupTitleHeight;
+    }
+  }
+}
+
+/**
+ * 强制清空图像,重绘
+ */
+GanttChart.prototype.forceRefreshGraph = function() {
+  this.tasks.forEach((topTask) => {
+    topTask.gGroup = null;
+  });
+  this.gCanvas.destroy();
+  this.initDrawingReady();
+}
+
+/**
+ * 准备绘制,用于初始化和强制刷新
+ */
+GanttChart.prototype.initDrawingReady = function() {
+  this.initCanvas();
+  this.initDragHandler();
+  this.drawTimeZone();
+  this.processData();
+  this.drawTasks();
+  this.graphGroup = null
+}
+
+/**
+ * 翻页
+ */
+GanttChart.prototype.pageTo = function(dir = 'next') {
+  if (dir == 'next') {
+    // 向后翻页`
+    this.startAt = this.startAt.add(this.daysCount, 'days');
+    this.offsetDis = 0
+  } else {
+    // 向前翻页
+    this.startAt = this.startAt.subtract(this.daysCount, 'days');
+    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'), this.offsetDis);
+  // offsetDis = viewWidth;
+  this.forceRefreshGraph();
+}
+// 上次点击时间,用于滚动时误触停止
+let lastClickAt = null;
+/**
+ * 执行拖动
+ * 改变graphDiv 滚动距离
+ * 到达边界距离后,刷新页面
+ */
+GanttChart.prototype.doDrag = function(sEvent, eEvent) {
+  if (sEvent == null) {
+    sEvent = this.startEvent;
+  }
+  
+  let sPos = sEvent.clientX;
+  let cPos = eEvent.clientX;
+  // 滚动距离
+  let dis = cPos - sPos;
+  let tempDis = this.offsetDis
+  // console.log('offsetDis before:', this.offsetDis, dis)
+  this.offsetDis = this.offsetDis - dis / 2;
+  // 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'),this.offsetDis);
+    this.offsetDis = this.viewWidth;
+    this.pageTo('prev');
+  }
+  if (this.offsetDis - 20 >= 2964 ){ //cWidth - viewWidth) {
+    // 向后滑动,向后翻页
+    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;
+}
+
+/**
+ * 初始化抓取拖动事件
+ */
+
+GanttChart.prototype.initDragHandler = function() {
+  this.graphDiv.scrollLeft = this.offsetDis;
+  let _canvas = document.querySelector('#ganttContainer>canvas');
+  _canvas.addEventListener('mousedown', (ev) => {
+    this.draging = true;
+    this.startEvent = ev;
+    this.dragingEvent = null;
+    this.endEvent = null;
+    this.lastClickAt = new Date();
+    this.lastClickAt = ev;
+    this.lastDragEv = ev;
+  });
+
+  _canvas.addEventListener('mouseup', (ev) => {
+    this.draging = false;
+    this.endEvent = ev;
+  });
+
+  _canvas.addEventListener('mousemove', (ev) => {
+    // console.log('this over', this)
+    if (this.draging) {
+      if (new Date() - this.lastClickAt < 20) {
+        return false;
+      }
+      this.dragingEvent = ev;
+      this.doDrag(this.lastDragEv, ev);
+      this.lastDragEv = ev;
+    }
+  });
+  _canvas.addEventListener('mouseleave', (ev) => {
+    console.log('leave...恢复')
+    this.draging = false;
+    this.endEvent = ev;
+  });
+}
+/**
+ * 初始化画布
+ *
+ */
+
+GanttChart.prototype.initCanvas = function() {
+  this.gCanvas = new G.Canvas({
+    container: 'ganttContainer',
+    width: this.cWidth,
+    height: 800,
+  });
+}
+
+/**
+ * 绘制时间区域
+ */
+
+GanttChart.prototype.drawTimeZone = function() {
+  console.log('时间段', this.startAt.format('YYYY-MM-DD'),this.endAt.format('YYYY-MM-DD'));
+  let start = moment(this.startAt);
+  let timeGroup = this.gCanvas.addGroup();
+  timeGroup._tname = 'TimeGroup';
+  // 绘制第一级
+  timeGroup.addShape('text', {
+    attrs: {
+      x: 20,
+      y: 20,
+      fontSize: 12,
+      text: start.format('YYYY-MM'),
+      lineDash: [10, 10],
+      fill: '#8D9399',
+    },
+  });
+  timeGroup.addShape('text', {
+    attrs: {
+      x: 20 + this.viewWidth,
+      y: 20,
+      fontSize: 12,
+      text: start.add(this.daysCount / 3, 'days').format('YYYY-MM'),
+      lineDash: [10, 10],
+      fill: '#8D9399',
+    },
+  });
+  timeGroup.addShape('text', {
+    attrs: {
+      x: 20 + this.viewWidth * 2,
+      y: 20,
+      fontSize: 12,
+      text: start.add(this.daysCount / 3, 'days').format('YYYY-MM'),
+      lineDash: [10, 10],
+      fill: '#8D9399',
+    },
+  });
+  let startSecond = moment(this.startAt);
+  // 绘制第二级
+  for (let i = 0; i < this.daysCount; i++) {
+    let timeText = startSecond.add(1, 'days').format('DD');
+    timeGroup.addShape('text', {
+      attrs: {
+        x: 40 * i,
+        y: 40,
+        fontSize: 10,
+        text: timeText,
+        lineDash: [10, 10],
+        fill: '#8D9399',
+      },
+    });
+  }
+}
+
+/**
+ * 处理点击
+ */
+GanttChart.prototype.handleClick = function(task, flag, ev) {
+  // 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
+    console.log('show:', task);
+  } else if (flag === 'leave'){
+    // detailDiv.style.display = 'none'
+    console.log('hide:', task);
+  } else {
+    this.callback(task);
+    console.log('click:', task);
+  }
+}
+
+
+/**
+ * 根据任务状态区分颜色
+ * 
+ */
+GanttChart.prototype.statusColor =function(task) {
+  switch (task.status) {
+    case '按时完成':
+      return 'aqua';
+      break;
+    case '计划批准':
+      return '#ff9800';
+      break;
+    case '已完成':
+      return '#19b720';
+      break;
+    default:
+      break;
+  }
+}
+
+/**
+ * 判断任务是否在视图内
+ * 
+ */ 
+GanttChart.prototype.isInView = function(task) {
+  let isLessThanEndAt = (task.endDate <= this.startAt.format('YYYY-MM-DD'))
+  let isGreaterThanStartAt = task.startDate >= this.endAt.format('YYYY-MM-DD')
+  return !(isLessThanEndAt || isGreaterThanStartAt)
+}
+
+/**
+ * 分组绘制任务块
+ *
+ */
+
+GanttChart.prototype.drawTasks = function() {
+  if (this.graphGroup) {
+    this.graphGroup.clear();
+  } else {
+    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;
+      // 第二层循环,用于 区分具体多少任务,例如,维保-商管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 + this.rowSpanDis)),
+                width: pos.width,
+                height: this.taskRowHeight,
+                fill: this.statusColor(_taskItem),
+                stroke: 'black',
+                radius: [2, 4],
+              },
+            });
+            rectEl._pdata = _taskItem;
+            rectEl.on('mouseover', (ev) => {
+              this.handleClick(ev.target, 'enter', ev);
+            });
+            rectEl.on('mouseleave', (ev) => {
+              this.handleClick(ev.target, 'leave', ev);
+            });
+            rectEl.on('click', (ev) => {
+              this.handleClick(ev.target, 'click', ev);
+            });
+          }
+        });
+      });
+
+      taskGroup.show();
+    } else {
+      if (topTask.gGroup) {
+        // topTask.gGroup.hide()
+        topTask.gGroup = null;
+      }
+    }
+  });
+}
+
+/**
+ * 根据 Task 计算矩形位置
+ *
+ */
+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(taskItem.startDate);        
+  let secondsEndAt = duraEndAt/1000
+  return {
+    x: secondsStartAt * this.timePerPix,
+    y: 0,
+    width: secondsEndAt * this.timePerPix,
+    height: 0,
+  };
+}
+
+/**
+ * 主函数
+ *
+ */
+
+GanttChart.prototype.main = function() {  
+  this.initDrawingReady();
+}

+ 23 - 7
src/views/analysis/CoreDeviceReport.vue

@@ -102,7 +102,9 @@
       <el-dialog :title="detailTitle" :visible.sync="showDetail" width="1260px">
         <div class="detail-container">
           <div class="pictures-menu">
-
+            <div v-for="(item) in pictureList" :key="'id_' + item.id" class="item">
+              <img :src="item.url" alt="">
+            </div>
           </div>
         </div>
       </el-dialog>
@@ -150,6 +152,7 @@ export default {
 
       showDetail: false, // 显示照片、报告详情
       detailTitle: '图片预览', // 弹窗名称
+      pictureList: [], // 图片列表
     }
   },
 
@@ -188,7 +191,6 @@ export default {
           } else {
             this.systemId = newData[0].id;
           }
-          console.log('this', this.$route)
           this.getEquipmentOfSystem();
         }
       })
@@ -250,7 +252,7 @@ export default {
       }
       let url = `/data/glsms_asset/query?plazaId=1000423&page=${this.curPage}&size=${this.pageSize}`;
       if (_.trim(this.searchKey) !== '') {
-        url = `${url}&keyword=${this.searchKey}`
+        url = `${url}&keyword=${this.searchKey}:sbjc,sbjbm`
       }
       queryTableData(url, query).then((res) => {
         const { result, count, data } = res;
@@ -368,13 +370,24 @@ export default {
      */
     getDetailData(val) {
       let param = {
-        file_type: 1, // val.file_type
-        file_type_id: 2467908, // val.file_type_id
+        file_type: 0, // val.file_type
+        file_type_id: 1144, // val.file_type_id
         type: this.detailTitle === '图片预览'? 0 : 1
       }
 
       queryDetailData('/data/base/queryFileDetails', param).then((res) => {
         console.log('res', res)
+        const { result, data } = res;
+        if (result === 'success') {
+          let newData = [];
+          _.forEach(data, (item) => {
+            newData.push({
+              id: item.id,
+              url: item.urlname
+            })
+          })
+          this.pictureList = newData;
+        }
       })
     }
   }
@@ -492,8 +505,11 @@ export default {
     .pictures-menu{
       margin-right: 21px;
       width: 180px;
+      .item{
+        >img{
+          width: 180px;
+        }
+      }
     }
-
   }
-
 </style>

+ 3 - 1
src/views/analysis/GanttChart.vue

@@ -263,10 +263,11 @@ export default {
           console.log('taskData', taskData)
           let width = this.$refs.chartContainer.offsetWidth;
           window.gc = new GanttChart({
+            chartParentContainer: 'chartContainer',
+            chartContainer: 'ganttContainer',
             viewWidth: width,
             cWidth: 3*width,
             tasks: taskData,
-            chartContainer: 'chartContainer',
             daysCount: parseInt(3*width/40),
             callback: this.showDialog
           });
@@ -422,6 +423,7 @@ export default {
     .chart-container{
       flex: 1;
       overflow: hidden;
+      background: #fff;
     }
   }
   .dialog-container{