Browse Source

于涵写的自定义Gantt开发

wyh 1 year ago
parent
commit
a639e71324
1 changed files with 458 additions and 0 deletions
  1. 458 0
      itdmWeb/src/views/module-iTDM/itdmGongdanMaster/uGantt.vue

+ 458 - 0
itdmWeb/src/views/module-iTDM/itdmGongdanMaster/uGantt.vue

@@ -0,0 +1,458 @@
+<template>
+  <div class="app-container">
+    
+    <div class="u-gantt-container u-flex">
+      <el-table
+        :data="taskLists" 
+        stripe border
+        :cell-class-name="tableCellClassName"
+        :header-cell-class-name="tableCellClassName"
+        @row-dblclick="rowDblclick">
+        <template v-for="(item, index) in configColumns">
+          <el-table-column
+            :prop="item.name"
+            :label="item.label"
+            :fixed="item.fixed"
+            :width="item.width"
+            :align="item.align"
+            :key="index"
+            show-overflow-tooltip
+          ></el-table-column>
+        </template>
+      </el-table>
+      <div class="u-gantt">
+        <div class="u-gantt-title u-flex" >
+          <div v-for="(item, index) in uGanttColumns" :key="index" class="item-title">{{ item.label}}</div>
+        </div>
+        <div class="u-gantt-content">
+          <div class="u-gantt-bg">
+            <div v-for="(item, tr) in taskLists" :key="tr" class="item-tr u-flex">
+              <div class="item-td" v-for="(item, td) in uGanttColumns" :key="td"></div>
+            </div>
+          </div>
+          <div class="u-gantt-task">
+
+              <div class="u-gantt-task-content uGanttTaskItem" ref="uGanttTaskItem" v-for="(item, index) in taskLists" :key="index" :style="setStyle(item)">
+                <!-- <span class="resize" ref="`resize${index}}`" @mousedown="dragControllerDiv(index)"></span> -->
+                <div class="u-gantt-task-drag" ref="uGanttDrag"></div>
+                <div class="u-gantt-task-resize resize-left" ref="uGanttResizeL"></div>
+                <div class="u-gantt-task-text">{{ item.content }}</div>
+                <div class="u-gantt-task-resize resize-right" ref="uGanttResizeR"></div>
+              </div>
+            
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 双击事件弹窗 -->
+    <el-dialog title="修改" :visible.sync="dialogVisible" width="40%">
+      <div>
+        开始:<el-date-picker v-model="currentDbEdit.task_start" type="date" value-format="yyyy-MM-dd" placeholder="选择日期"></el-date-picker>
+      </div>
+      <div>
+        结束:<el-date-picker v-model="currentDbEdit.task_end" type="date" value-format="yyyy-MM-dd" placeholder="选择日期"></el-date-picker>
+      </div>
+      <!-- 其他需要自定义的弹窗数据 -->
+      <slot/>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="cancel">取 消</el-button>
+        <el-button type="primary" @click="submit">确 定</el-button>
+      </span>
+    </el-dialog>
+
+
+
+  </div>
+</template>
+
+<script>
+  export default {
+    data(){
+      return {
+        configColumns: [
+          { name: "testItems", label: "检测项目", width: 80, fixed: true, resize: true, align: "center",resize: true, tree: true },
+          { name: "sampleName", label: "样品名称", width: 90, fixed: true, resize: true, align: "center" },
+          { name: "task_start", label: "开始时间", width: 100, fixed: true, resize: true, align: "center" },
+          { name: "task_end", label: "结束时间", width: 100, fixed: true, resize: true, align: "center" },
+        ],
+        taskLists: [{
+            id: 0,
+            testItems: 'ceshi',
+            sampleName: 'ceshi',
+            task_start: '2023-07-03',
+            task_end: '2023-07-04',
+            statusC: '0',
+            content: '111'
+          }, {
+            id: 1,
+            testItems: '测试',
+            sampleName: '测试',
+            task_start: '',
+            task_end: '',
+            statusC: '0',
+          }, {
+            id: 2,
+            testItems: 'ceshi',
+            sampleName: 'ceshi',
+            task_start: '2023-07-06',
+            task_end: '2023-07-10',
+            statusC: '1',
+          }, {
+            id: 3,
+            testItems: '测试',
+            sampleName: '测试',
+            task_start: '',
+            task_end: '',
+            statusC: '1',
+          },{
+            id: 4,
+            testItems: '测试',
+            sampleName: '测试',
+            task_start: '',
+            task_end: '',
+            statusC: '1',
+          },
+          {
+            id: 5,
+            testItems: '测试',
+            sampleName: '测试',
+            task_start: '',
+            task_end: '',
+            statusC: '1',
+          },
+          {
+            id: 6,
+            testItems: '测试',
+            sampleName: '测试',
+            task_start: '',
+            task_end: '',
+            statusC: '1',
+          },
+          {
+            id: 7,
+            testItems: '测试',
+            sampleName: '测试',
+            task_start: '',
+            task_end: '',
+            statusC: '1',
+          },
+          {
+            id: 8,
+            testItems: '测试',
+            sampleName: '测试',
+            task_start: '',
+            task_end: '',
+            statusC: '1',
+          },],
+
+        // 当前双击的数据
+        currentDbEdit: {},
+        dialogVisible: false,
+      }
+    },
+    computed: {
+      // 甘特图标题日期分配
+      uGanttColumns() {
+        // 获取标准时间
+        var nowdays = new Date()
+        // 获取当年
+        var currentYear = new Date().getFullYear()
+        // 获取当月
+        var currentMonth = new Date().getMonth() + 1
+        // 获取当天
+        var nowDay = new Date().getDate()
+        // 获取当前月有多少天
+        var currentMonthNum = new Date(currentYear, currentMonth, 0).getDate()
+        console.log(nowDay, currentMonth, currentMonthNum)
+        // 
+        // let now = new Date(nowDay)
+        // console.log(nowdays, now)
+        // 当前月份所有日期集合
+        let currentMonthArr = []
+        for (let i = 1; i <= currentMonthNum; i++) {
+          // let day = nowdays.setDate(i);
+          // console.log(day)
+          // 年月日(yyyy-MM-dd)
+          let dateLabel = (currentMonth < 10 ? '0' + currentMonth : currentMonth) + "月" + (i < 10 ? '0' + i : i) + "日";
+          let dateName = currentYear + "-" + (currentMonth < 10 ? '0' + currentMonth : currentMonth) + "-" + (i < 10 ? '0' + i : i);
+          // let day = 
+          currentMonthArr.push({label: dateLabel, name: dateName});
+        }
+        console.log(currentMonthArr)
+        return currentMonthArr
+      },
+      
+    },
+    mounted () {
+      this.uGanttDrag()
+      this.uGanttResizeL()
+      this.uGanttResizeR()
+    },
+    methods: {
+      setStyle(item){
+        var startIndex = this.uGanttColumns.findIndex(res => res.name === item.task_start)
+        var endIndex = this.uGanttColumns.findIndex(res => res.name === item.task_end)
+        var trIndex = this.taskLists.findIndex(res => res.id === item.id)
+        // console.log(trIndex, this.taskLists)
+        var style = {
+          left: 70 * startIndex + 'px',
+          width: 70 * (endIndex - startIndex + 1) + 'px',
+          top: (34 * trIndex + 2) + 'px'
+        }
+        return style
+      },
+      // 位移事件
+      uGanttDrag(){
+        var _this = this
+        var uGanttDrag = this.$refs.uGanttDrag;
+        var uGanttTaskItem = this.$refs.uGanttTaskItem;
+        for (let i = 0; i < uGanttDrag.length; i++) {
+          uGanttDrag[i].onmousedown = function (e) {
+            const offsetLeft = uGanttTaskItem[i].offsetLeft
+            const offsetWidth = uGanttTaskItem[i].offsetWidth
+            var startX = e.clientX;
+            var moveLen
+            var ganttIndex = Math.trunc(uGanttTaskItem[i].offsetTop/34)
+            document.onmousemove = function (e) {
+              var endX = e.clientX;
+              moveLen = offsetLeft + ( endX - startX )
+              uGanttTaskItem[i].style.left = moveLen + 'px'
+              uGanttDrag[i].style.cursor = 'move'
+              
+            }
+            document.onmouseup = function (evt) {
+              uGanttTaskItem[i].style.left = Math.round(moveLen/70) * 70 + 'px';
+              var startNum = (uGanttTaskItem[i].offsetLeft)/70
+              var endNum = (offsetWidth / 70) + startNum
+              // // 普通赋值
+              // // _this.taskLists[0].task_end = _this.uGanttColumns[num - 1].name
+              // // 强制赋值刷新
+              console.log(ganttIndex)
+              _this.$set(_this.taskLists[ganttIndex], 'task_start', _this.uGanttColumns[startNum].name)
+              _this.$set(_this.taskLists[ganttIndex], 'task_end', _this.uGanttColumns[endNum - 1].name)
+              uGanttDrag[i].style.cursor = 'pointer'
+              // // 强制刷新
+              // // _this.$forceUpdate()
+              document.onmousemove = null;
+              document.onmouseup = null; 
+              document.releaseCapture && document.releaseCapture();
+            }
+            document.setCapture && document.setCapture();
+            return false;
+          }
+        }
+      },
+      // 改变大小
+      uGanttResizeL(){
+        var _this = this
+        var resize = this.$refs.uGanttResizeL;
+        var uGanttTaskItem = this.$refs.uGanttTaskItem;
+        for (let i = 0; i < resize.length; i++) {
+          resize[i].onmousedown = function (e) {
+            var startX = e.clientX;
+            var ganttIndex = Math.trunc(uGanttTaskItem[i].offsetTop/34)
+            const offsetLeft = uGanttTaskItem[i].offsetLeft;
+            const offsetWidth = uGanttTaskItem[i].offsetWidth
+            var moveLen
+            var ganttWidth
+            document.onmousemove = function (e) {
+              var endX = e.clientX;
+              moveLen = offsetLeft - (startX - endX);
+              ganttWidth = (startX - endX) + offsetWidth
+              if (ganttWidth < 70){
+                ganttWidth = 70
+                moveLen = offsetLeft + offsetWidth - 70
+              }
+              
+              uGanttTaskItem[i].style.left = moveLen + 'px';
+              uGanttTaskItem[i].style.width = ganttWidth + 'px';
+            }
+            document.onmouseup = function (evt) {
+              uGanttTaskItem[i].style.left = Math.round(moveLen/70) * 70 + 'px';
+              uGanttTaskItem[i].style.width = Math.round(ganttWidth/70) * 70 + 'px';
+              var num = (uGanttTaskItem[i].offsetLeft)/70
+              console.log(num)
+              // 普通赋值
+              // _this.taskLists[0].task_end = _this.uGanttColumns[num - 1].name
+              // 强制赋值刷新
+              console.log(ganttIndex)
+              _this.$set(_this.taskLists[ganttIndex], 'task_start', _this.uGanttColumns[num].name)
+              // 强制刷新
+              // _this.$forceUpdate()
+              document.onmousemove = null;
+              document.onmouseup = null; 
+              document.releaseCapture && document.releaseCapture();
+            }
+            document.setCapture && document.setCapture();
+            return false;
+          }
+        }
+      },
+      // 改变大小
+      uGanttResizeR(){
+        var _this = this
+        var resize = this.$refs.uGanttResizeR;
+        var uGanttTaskItem = this.$refs.uGanttTaskItem;
+        // var ganttIndex = this.taskLists.findIndex(res=>res.id === 0)
+        for (let i = 0; i < resize.length; i++) {
+          resize[i].onmousedown = function (e) {
+            var ganttIndex = Math.trunc(uGanttTaskItem[i].offsetTop/34)
+            var startX = e.clientX;
+            resize[i].left = resize[i].offsetLeft;
+            var moveLen
+            document.onmousemove = function (e) {
+              var endX = e.clientX;
+              moveLen = resize[i].left + (endX - startX);
+              if (moveLen < 70) moveLen = 70; 
+    
+              resize[i].style.left = moveLen;
+              
+              uGanttTaskItem[i].style.width = moveLen + 'px';
+            }
+            document.onmouseup = function (evt) {
+              uGanttTaskItem[i].style.width = Math.round(moveLen/70) * 70 + 'px';
+              var num = (uGanttTaskItem[i].offsetLeft + uGanttTaskItem[i].offsetWidth)/70
+              // 普通赋值
+              // _this.taskLists[0].task_end = _this.uGanttColumns[num - 1].name
+              // 强制赋值刷新
+              _this.$set(_this.taskLists[ganttIndex], 'task_end', _this.uGanttColumns[num - 1].name)
+              // 强制刷新
+              // _this.$forceUpdate()
+              document.onmousemove = null;
+              document.onmouseup = null; 
+              document.releaseCapture && document.releaseCapture();
+            }
+            document.setCapture && document.setCapture();
+            return false;
+          }
+        }
+      },
+      tableCellClassName({ row, column, rowIndex, columnIndex }){
+        //把每一行的索引放进row--可以用于获取index
+        // row.index = rowIndex;
+        return 'u-table-cell'
+      },
+      // 双击事件
+      rowDblclick(row, column, event){
+        console.log(row, column, event)
+        // 深拷贝:直接赋值会有还没点确定,甘特图部分就已经改变的bug
+        this.currentDbEdit = JSON.parse(JSON.stringify(row))
+        this.dialogVisible = true
+      },
+      cancel(){
+        this.currentDbEdit = {}
+        this.dialogVisible = false
+      },
+      submit(){
+        var taskIndex = this.taskLists.findIndex(res=>res.id === this.currentDbEdit.id)
+        this.taskLists[taskIndex].task_start = this.currentDbEdit.task_start
+        this.taskLists[taskIndex].task_end = this.currentDbEdit.task_end
+        this.dialogVisible = false
+        this.currentDbEdit = {}
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+.u-flex{
+  display: flex;
+}
+.u-gantt-container{
+  // width: calc(100vw - 240px);
+  .el-table{
+    .u-table-cell{
+      padding: 0 !important;
+      height: 34px !important;
+      line-height: 34px !important;
+      box-sizing: border-box !important;
+    }
+    .el-table--enable-row-transition .el-table__body td.el-table__cell{
+      padding: 0 !important;
+    }
+    
+  }
+  .u-gantt{
+    width: calc(100% - 371px);
+    border-top: 1px solid #ebebeb;
+    border-left: 1px solid #ebebeb;
+    overflow: auto;
+  }
+  .u-gantt-title{
+    .item-title{
+      width: 70px;
+      height: 34px;
+      line-height: 34px;
+      text-align: center;
+      border-right: 1px solid #ebebeb;
+      border-bottom: 1px solid #ebebeb;
+      font-size: 12px;
+      color: #787878;
+      flex-shrink: 0; // 设置宽度不够时,元素不压缩而是超出滚动
+    }
+  }
+  .u-gantt-content{
+    position: relative;
+    // 底层表格线框
+    .u-gantt-bg{
+      // position: absolute;
+      .item-tr{
+        height: 34px;
+      }
+      .item-td{
+        width: 70px;
+        height: 34px;
+        border-right: 1px solid #ebebeb;
+        border-bottom: 1px solid #ebebeb;
+        flex-shrink: 0; // 设置宽度不够时,元素不压缩而是超出滚动
+      }
+    }
+    // 项目甘特条
+    .u-gantt-task{
+      // position: absolute;
+      // top: 0;
+      // left: 0;
+      // right: 0;
+      // bottom: 0;
+      // background-color: #b72222;
+      .u-gantt-task-content{
+        position: absolute;
+        top: 36px;
+        left: 140px;
+        width: 140px;
+        height: 30px;
+        line-height: 30px;
+        background-color: #44c2e5;
+        border-radius: 2px;
+        .u-gantt-task-drag{
+          position: absolute;
+          top: 0;
+          left: 1px;
+          right: 1px;
+          bottom: 0;
+          cursor: pointer;
+        }
+        .u-gantt-task-resize{
+          position: absolute;
+          width: 8px;
+          height: 30px;
+          top: 0;
+          cursor: w-resize;
+        }
+        .resize-left{
+          left: -7px;
+        }
+        .u-gantt-task-text{
+          color: #fff;
+          text-align: center;
+          
+        }
+        .resize-right{
+          right: -7px;
+        }
+      }
+    }
+  }
+}
+</style>