2023-03-15

排程甘特图 v1.0

image.png
<template>
    <div id="gante">
      <el-button @click="refresh" style="margin-bottom:5px">刷新(测试)</el-button>
      <table border="1" cellpadding="8px" class="gante-table" v-loading="loading">
        <tr>
          <th style="width:200px"></th>
          <th style="width:100px" colspan="2" v-for="item in headerData" :key="item.key">{{ item.value }}</th>
        </tr>
        <tr v-for="(item, index) in rows" :key="index" :class="{ firstline: index == 0}">
          <template v-if="index == 0">
            <td class="cell_td">设备</td>
            <td class="cell_td" colspan="2" v-for="item in headerData" :key="item.id"></td>
          </template>
  
          <template v-else>
            <td>资源 {{index}}</td>
            <template v-for="(r, index) in item.row">
              <td :key="index" :style="{ position: index % 2 == 0 ? 'relative' : 'static' }">
  
                <div :class="{'contant_block_hover': colorMap.get(r.status).length}" @mouseover="mouseover(item.id, r.iid, r.status == 'Danger')" @mouseleave="mouseleave(item.id, r.iid,  r.status == 'Danger')" :style="{backgroundColor: colorMap.get(r.status)}" class="center contant_block" v-if="index % 2 == 0">
                  {{colorMap.get(r.status) ? (r.status=="Danger"? '' : '100%') : '0%'}}
                  <div class="contant_hover" v-show="r.showContant"  @mouseleave.stop @mouseover.stop >
                    设备:QG#01切割机 <br>
                    故障起始时间:2023-2-27 8:00 <br>
                    故障修复时间:2023-2-27 12:00 <br>
                    影响任务单个数:10 <br>
                  </div>
  
                </div>
  
              </td>
            </template>
          </template>
        </tr>
      </table>
    </div>
  
  </template>
  
  <script>
  export default {
    name: 'gantt',
    data() {
      return {
        rows: [],
        bodyData: [],
        headerData: [],
        loading: true,
        colorMap: new Map()
      };
    },
    props: {
    },
    created() {
      this.colorMap.set('Success', '#67C23A')
      this.colorMap.set('Warning', '#E6A23C')
      this.colorMap.set('Danger', '#F56C6C')
      this.colorMap.set('Info', '#909399')
      this.colorMap.set('none', '')
  
      this.createData()
  
    },
    beforeDestroy() {
  
    },
    watch: {
  
    },
    methods: {
      createData() {
        const colorMap = ['Success', 'Warning', 'Danger', 'Info', 'none']
        this.loading = true
        new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve(); 
          }, 1000)
        }).then(() => {
          this.headerData = []
          this.rows = [];
  
          for (let index = 0; index < 6; index++) {
            const obj = { row: [] };
            obj.id = this.uuid()
  
            for (let index = 0; index < 22; index++) {
              const num = Math.floor(Math.random()*Math.floor(5));
  
              const _obj = {}
              _obj.value = 'contant' + '-' + index
              _obj.iid = this.uuid()
              _obj.showContant = false;
              _obj.status = colorMap[num]
              obj.row.push(_obj)
            }
  
            this.rows.push(obj);
          }
  
          for (let index = 0; index < 11; index++) {
            const obj = {};
            obj.value = this.getDateFun(index)
            obj.key = this.uuid()
            this.headerData.push(obj)
          }
        }).finally(() => {
          this.loading = false
        })
      },
      uuid() {
          return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
              var r = Math.random() * 16 | 0,
                  v = c == 'x' ? r : (r & 0x3 | 0x8);
              return v.toString(16);
          });
      },
      refresh() {
        this.createData();
      },
      mouseover(id, iid, key) {
        if(!key) return
        const index = this.rows.findIndex(item => item.id == id);
        if(index != -1) {
          const i = this.rows[index].row.findIndex(item => item.iid == iid)
          if(i != -1) {
            this.rows[index].row[i].showContant = true
          }
        }
      },
      mouseleave(id, iid, key) {
        if(!key) return
        console.log('mouseleave')
        const index = this.rows.findIndex(item => item.id == id);
        if(index != -1) {
          const i = this.rows[index].row.findIndex(item => item.iid == iid)
          if(i != -1) {
            this.rows[index].row[i].showContant = false
          }
        }
      },
      getDateFun(index) {
        const day = new Date();
        day.setTime(day.getTime() + index * 24*60*60*1000);
        return day.getFullYear()+"-" + (day.getMonth()+1) + "-" + day.getDate();
      },
      bgcFun(status) {
        console.log('???????????????????????????????')
        return "background-color: #67C23A"
      }
    }
  }
  </script>
  <style lang="scss" scoped>
    #gante {
      margin-top: 10px;
      padding: 10px;
      padding-bottom: 30px;
      overflow-x: auto;
      background-color: #fff;
      .gante-table {
        border: none;
        width: 1300px;
      }
    }
    .center {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .contant_block {
      cursor: pointer; 
      width:90px; 
      height:30px; 
      border-radius: 3px;
      position: absolute; 
      top: 3px; 
      left: 5px;
    }
    .contant_block_hover:hover {
      // transform: scale(1.02);
      border: 2px solid #cccccc;
    }
    .firstline {
      line-height: 6px;
    }
    .cell_td {
      width: 150px;
    }
    .contant_hover {
      z-index:9999; 
      position:absolute; 
      left:100px; 
      width:220px; 
      height:100px; 
      padding: 5px;
      background-color:#ffffff;
      border: 1px solid #cccccc;
    }
  </style>

排程甘特图 v2.0

image.png
<template>
  <div id="gante">
    <el-button @click="refresh" style="margin-bottom:5px">刷新(测试)</el-button>
    <table border="1" cellpadding="8px" class="gante-table" v-loading="loading">
      <tr style="text-align:center;">
        <th style="width:200px"></th>
        <th style="width:200px" colspan="2" v-for="item in headerData" :key="item.key">{{ item.value }}</th>
      </tr>
      <tr v-for="(item, index) in rows" :key="index" :class="{ firstline: index == 0}">
        <template v-if="index == 0">
          <td>设备</td>
          <td colspan="2" v-for="item in headerData" :key="item.id">
              <div style="display:flex;justify-content:space-between;">
                  <span class="time_item">02</span>
                  <span class="time_item">04</span>
                  <span class="time_item">06</span>
                  <span class="time_item">08</span>
                  <span class="time_item">10</span>
                  <span class="time_item">12</span>
                  <span class="time_item">14</span>
                  <span class="time_item">16</span>
                  <span class="time_item">18</span>
                  <span class="time_item">20</span>
                  <span class="time_item">22</span>
              </div>
          </td>
        </template>

        <template v-else>
          <td>资源 {{index}}</td>
          <template v-for="(r, index) in item.row">
            <td :key="index" :style="{ position: index % 2 == 0 ? 'relative' : 'static' }">

              <template v-if="index != item.row.length - 2 && index % 2 == 0" >
                <div :class="{'contant_block_hover': colorMap.get(r.am.status).length}" @mouseover="mouseover(item.id, r.am.iid, r.am.status == 'Danger','am')" @mouseleave="mouseleave(item.id, r.am.iid,  r.am.status == 'Danger', 'am')" :style="{border: '1px ' + 'solid ' + colorMap.get(r.am.status)}" class="center contant_block">
                  <div :style="{backgroundColor: colorMap.get(r.am.status),height: r.am.percentage * 100 + '%', width: '100%' }">
                  </div>
                  <div style="position: absolute;left:50%;transform: translateX(-50%);">
                    {{r.am.percentage * 100 }}%
                  </div>
                  <div class="contant_hover" v-show="r.am.showContant"  @mouseleave.stop @mouseover.stop >
                    设备:QG#01切割机 <br>
                    故障起始时间:2023-2-27 8:00 <br>
                    故障修复时间:2023-2-27 12:00 <br>
                    影响任务单个数:10 <br>
                  </div>

                </div>

                <div style="left:196px" :class="{'contant_block_hover': colorMap.get(r.pm.status).length}" @mouseover="mouseover(item.id, r.pm.iid, r.pm.status == 'Danger','pm')" @mouseleave="mouseleave(item.id, r.pm.iid,  r.pm.status == 'Danger','pm')" :style="{border: '1px ' + 'solid ' + colorMap.get(r.pm.status), width: '117px'}" class="center contant_block">
                  <div :style="{backgroundColor: colorMap.get(r.pm.status),height: r.pm.percentage * 100 + '%', width: '100%' }">
                  </div>
                  <div style="position: absolute;left:50%;transform: translateX(-50%);">
                    {{r.pm.percentage * 100 }}%
                  </div>
                  <div class="contant_hover" v-show="r.pm.showContant"  @mouseleave.stop @mouseover.stop >
                    设备:QG#01切割机 <br>
                    故障起始时间:2023-2-27 8:00 <br>
                    故障修复时间:2023-2-27 12:00 <br>
                    影响任务单个数:10 <br>
                  </div>
                </div>
              </template>

            </td>
          </template>
        </template>
      </tr>
    </table>
  </div>

</template>

<script>
export default {
  name: 'gantt',
  data() {
    return {
      rows: [],
      bodyData: [],
      headerData: [],
      loading: true,
      colorMap: new Map()
    };
  },
  props: {
  },
  created() {
    this.colorMap.set('Success', '#67C23A')
    this.colorMap.set('Warning', '#E6A23C')
    this.colorMap.set('Danger', '#F56C6C')
    this.colorMap.set('Info', '#909399')
    this.colorMap.set('none', '')

    this.createData()

  },
  methods: {
    createData() {
      this.loading = true
      new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(); 
        }, 1000)
      }).then(() => {
        this.headerData = []
        this.rows = [];

        for (let index = 0; index < 6; index++) {
          this.rows.push(this.createBlockData());
        }

        for (let index = 0; index < 6; index++) {
          const obj = {};
          obj.value = this.getDateFun(index)
          obj.key = this.uuid()
          this.headerData.push(obj)
        }
      }).finally(() => {
        this.loading = false
      })
    },

    uuid() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0,
                v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    },

    createBlockData() {
      const obj = { row: [] };
      obj.id = this.uuid()
      obj.row = this.createBlockDataItem()
      return obj
    },

    createBlockDataItem() {
      const colorMap = ['Success', 'Warning', 'Danger', 'Info', 'none']
      const row = []
      for (let index = 0; index < 12; index++) {
        const _obj = {am:{},pm:{}}

        _obj.am.value = 'contant' + '-' + index
        _obj.am.iid = this.uuid()
        _obj.am.showContant = false;
        _obj.am.status = colorMap[Math.floor(Math.random()*Math.floor(5))]
        if(_obj.am.status !== 'none') {
          _obj.am.percentage = Math.random().toFixed(1) 
        }else {
          _obj.am.percentage = 0
        }

        _obj.pm.value = 'contant' + '-' + index
        _obj.pm.iid = this.uuid()
        _obj.pm.showContant = false;
        _obj.pm.status = colorMap[Math.floor(Math.random()*Math.floor(5))]
        if(_obj.pm.status !== 'none') {
          _obj.pm.percentage = Math.random().toFixed(1) 
        }else {
          _obj.pm.percentage = 0
        }


        row.push(_obj)
      }
      return row
    },

    refresh() {
      this.createData();
    },

    mouseover(id, iid, key, mark) {
      console.log('mouseover')
      if(!key) return
      const index = this.rows.findIndex(item => item.id == id);
      if(index != -1) {
        const i = this.rows[index].row.findIndex(item => item[mark].iid == iid)
        if(i != -1) {
          this.rows[index].row[i][mark].showContant = true
        }
      }
    },

    mouseleave(id, iid, key, mark) {
      if(!key) return
      console.log('mouseleave')
      const index = this.rows.findIndex(item => item.id == id);
      if(index != -1) {
        const i = this.rows[index].row.findIndex(item => item[mark].iid == iid)
        if(i != -1) {
          this.rows[index].row[i][mark].showContant = false
        }
      }
    },

    getDateFun(index) {
      const day = new Date();
      day.setTime(day.getTime() + index * 24*60*60*1000);
      return day.getFullYear()+"-" + (day.getMonth()+1) + "-" + day.getDate();
    },
  }
}
</script>
<style lang="scss" scoped>
  #gante {
    margin-top: 10px;
    padding: 10px;
    padding-bottom: 30px;
    overflow-x: auto;
    background-color: #fff;
    .gante-table {
      border: none;
      width: 1600px;
      // overflow: hidden;
    }
  }
  .center {
    display: flex;
    // justify-content: center;
    align-items: end;
  }
  .contant_block {
    z-index: 9;
    cursor: pointer; 
    width:116px; 
    height:30px; 
    border-radius: 3px;
    position: absolute; 
    top: 3px; 
    left: 80px;
  }
  .contant_block_hover:hover {
    z-index: 99999;
    border: 2px solid #cccccc;
  }
  .firstline {
    line-height: 6px;
  }
  .contant_hover {
    z-index:9999; 
    position: absolute; 
    left:120px; 
    width:220px; 
    height:100px; 
    padding: 5px;
    background-color:#ffffff;
    border: 1px solid #cccccc;
  }
  .time_item {
    flex:1;
    text-align:center
  }
</style>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 我们每个人都从单纯、热情、完整无缺,渐渐变得复杂、怯懦、支离破碎。遇到一些人,爱上一些人,忘记一些人。被伤害的同时...
    周公子爱坤坤阅读 123评论 0 1
  • 烦恼本无根,不捡自然无;忧愁本无源,不究自轻松。世间之事,一念而已,心中若有事事重,心中若无事事轻,淡定之人不负赘...
    考研学姐阅读 266评论 0 29
  • 烦恼本无根,不捡自然无;忧愁本无源,不究自轻松。世间之事,一念而已,心中若有事事重,心中若无事事轻,淡定之人不负赘...
    考研学姐阅读 264评论 0 30
  • 治国必先治党,党兴才能国强 习近平总书记在党的二十大报告...
    ayi_0ece阅读 76评论 0 0
  • 今天上课写作业时,我走到小晔的身边,看到他书写的字太小,每个字都是团在一起的,不会一笔一划的写。于是我拿了一本书写...
    gll123456阅读 69评论 0 0