简易版甘特图

如何去实现一个简易版的甘特图,下面是相关代码,也需要下载依赖有 Element UI和 dayjs

<template>

  <basic-container>

    <div class="gant-content">

      <th-page-button-group

        class="button-group"

        style="width:100%"

        v-if="!isPrint"

      >

        <el-date-picker

          v-model="currentTime"

          type="month"

          placeholder="选择月"

          @change="changeMonth"

          :clearable="false"

          style="float:right"

        >

        </el-date-picker>

      </th-page-button-group>

      <div :class="`plan-item plan-item-0`">

        <el-table

          :class="`table-0`"

          :data="planList"

          v-loading="loading"

          :header-cell-style="{textAlign: 'center', background:'#00aa94 !important', color: '#fff !important'}"

          height="100%"

        >

          <el-table-column

            type="index"

            align="center"

            width="40"

            label="序号"

          >

          </el-table-column>

          <el-table-column

            align="center"

            prop="serial"

            label="编号"

            width="120"

          >

          </el-table-column>

          <el-table-column

            align="center"

            width="120"

            prop="equipment"

            label="设备"

            class-name="equip"

          >

          </el-table-column>

          <el-table-column

            align="center"

            prop="planStartTime"

            label="开始时间"

            width="100"

          >

          </el-table-column>

          <el-table-column

            align="center"

            width="100"

            prop="planEndTime"

            label="结束时间"

          >

          </el-table-column>

          <el-table-column

            align="center"

            prop="jobContent"

            width="120"

            label="工作内容"

          >

          </el-table-column>

          <el-table-column

            align="center"

            prop="date"

            :label="currentTimes"

          >

            <el-table-column

              v-for="(col, day) in days"

              :key="day"

              align="center"

              class-name="gantt-item"

              :label="`${day + 1}`"

              width="32"

            >

              <template slot-scope="scope">

                <div

                  id="yidongdiv"

                  :class="hasTime(scope.row) ? 'hasTime' : ''"

                  :style="{background: checkBg(scope.row, day + 1)}"

                >

                  <span :class="day == 0 ? 'first-span' : ''">{{showText(scope.row, day + 1)}}</span>

                </div>

              </template>

            </el-table-column>

          </el-table-column>

        </el-table>

      </div>

      <!--endprint-->

    </div>

  </basic-container>

</template>

<script>

import { getGtViewInfoByDate } from '@/api/chart.js'

export default {

  name: 'gantt',

  data () {

    return {

      days: [],

      planList: [],

      currentTime: new Date().toString(),

      currentTimes: "",

      propsData: {

        planCategory: '',

        type: '',

        month: "",

        year: ''

      },

      isPrint: false,

      loading: true

    };

  },

  created () {

    this.changeMonth()

    // this.fetchData();

  },

  methods: {

    //页面渲染天数

    getDates () {

      this.days = []

      for (let i = 0; i < this.getCountDays(this.currentTime); i++) {

        this.days.push(i);

      }

    },

    //选择月份发送请求

    changeMonth () {

      this.loading = true

      this.currentTimes = this.dayjs(new Date(this.currentTime)).format('YYYY-MM')

      this.getDates()

      this.getGtViewInfo()

    },

    //获取每月有多少天

    getCountDays (time) {

      return this.dayjs(time).daysInMonth()

    },

    //发送请求获取数据

    async getGtViewInfo () {

      const { data } = await getGtViewInfoByDate({ currentTime: this.currentTimes })

      if (data.code == 0) {

        this.planList = data.data

      }

      this.loading = false

    },

    //背景色

    checkBg (data, day) {

      let { year, month } = this.propsData;

      month = new Date(this.currentTime).getMonth() + 1

      year = new Date(this.currentTime).getFullYear()

      let currentData = this.dayjs(`${ year }-${ month }-${ day }`).valueOf();

      let startData = this.dayjs(data.planStartTime.substring(0, 10)).valueOf();

      let endData = this.dayjs(data.planEndTime.substring(0, 10)).valueOf();

      if (currentData >= startData && currentData <= endData) {

        return '#00CCFF'

      }

    },

    showText (data, day) {

      let { year, month } = this.propsData;

      month = new Date(this.currentTime).getMonth() + 1

      year = new Date(this.currentTime).getFullYear()

      let currentData = this.dayjs(`${ year }-${ month }-${ day }`).valueOf();

      if (day == 1) {

        if (currentData > this.dayjs(data.planStartTime.substring(0, 10)).valueOf()) {

          return data.planStartTime.substring(0, 10);

        }

      } else if (day == this.days.length) {

        if (currentData < this.dayjs(data.planEndTime.substring(0, 10)).valueOf()) {

          return data.planEndTime.substring(0, 10);

        }

      }

    },

    hasTime (data) {

      let { year, month } = this.propsData;

      let startData = this.dayjs(data.planStartTime.substring(0, 10)).valueOf();

      let endData = this.dayjs(data.planEndTime.substring(0, 10)).valueOf();

      let yearStartData = this.dayjs(`${ year }-${ month }-${ 1 }`).valueOf();

      let yearEndData = this.dayjs(`${ year }-${ month }-${ this.days.length }`).valueOf();

      return startData < yearStartData || endData > yearEndData;

    }

  }

};

</script>

<style scoped lang="scss">

.gant-content {

  padding-bottom: 20px;

  height: 100%;

}

/deep/ .el-table td,

.el-table th {

  padding: 8px 0;

  min-height: 32px;

}

.gant-title {

  width: 1484px;

  border-bottom: 1px solid #ebeef5;

  text-align: center;

  line-height: 40px;

  font-weight: bold;

  background: #f3f4f7;

  color: #000;

}

/deep/ .el-table--border td {

  border-color: #e3e3e3;

}

/deep/ .el-table__header-wrapper {

  display: none;

}

/deep/ .table-0 .el-table__header-wrapper {

  display: block;

}

.plan-item {

  // box-sizing: border-box;

  width: 100%;

  height: calc(100% - 50px);

  position: relative;

  display: flex;

  justify-content: center;

  align-items: center;

  overflow: hidden;

  .plan-name {

    height: 100%;

    width: 100px;

    font-weight: bold;

    display: flex;

    .plan-text {

      padding: 0 10px;

      font-size: 13px;

      text-align: center;

      color: #000;

      flex: 1;

    }

  }

  &.plan-item-0 {

    .plan-text {

      transform: translateY(33px);

    }

  }

}

/deep/ .el-table {

  border-left: 1px solid #ebeef5;

  .el-table__row:last-child td {

    border-bottom: none;

  }

  &::before {

    height: 0;

  }

  .cell {

    padding: 0 !important;

    font-size: 12px;

  }

  .equip .cell {

    padding: 0 10px !important;

  }

  th {

    padding: 4px 0;

  }

  .gantt-item {

    position: relative;

  }

}

/deep/ .el-table--border,

.el-table--group {

  border-bottom: none;

  border-top: none;

}

.plan-title {

  height: 65px;

  line-height: 65px;

  font-weight: bold;

  text-align: center;

  color: #000;

  background: rgb(243, 244, 247) !important;

  position: absolute;

  top: 0;

  font-size: 12px;

  width: 100px;

  border-bottom: 1px solid #ebeef5;

}

#yidongdiv {

  width: 100%;

  color: #000;

  line-height: 18px;

  min-height: 18px;

  font-size: 10px;

  span {

    position: absolute;

    left: -40px;

    top: 50%;

    transform: translateY(-10px);

    display: inline-block;

    z-index: 5;

    &.first-span {

      left: unset;

      right: -40px;

    }

  }

}

.el-date-editor {

  margin-bottom: 10px;

}

</style>

上一篇:QT绘制雷达效果图


下一篇:CSS快捷的全屏和取消全屏