<template>
  <Card :title="title">
    <div class="gantt-chart">
      <div class="table" @scroll="handleScroll">
        <div class="thead">
          <div class="row">
            <div class="td">分部分项工程名称</div>
            <div class="td">开始日期</div>
            <div class="td">完成日期</div>
            <div class="td" v-for="date in dateList" :key="date">
              <div class="date">
                <div class="month">
                  {{ date }}
                </div>
                <div class="days">
                  <div class="day" v-for="day in getDays(date)" :key="day.num">{{ day.num }}</div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="tbody">
          <div class="row-groups" :class="{ open: openedIndex === i }" v-for="(p, i) in projects" :key="p.pName">
            <div class="row">
              <div class="td" @click="handleOpen(i)">{{ p.pName }}</div>
              <div class="td">{{ p.startTime }}</div>
              <div class="td">{{ p.endTime }}</div>
              <div class="td" v-for="date in dateList" :key="date + 'grid-date'">
                <div class="grids">
                  <div class="grid" v-for="day in getDays(date)" :key="'grid' + day.num" :ref="p.pName + '-' + day.date"></div>
                </div>
              </div>
              <div
                class="progress"
                :style="gantt"
                v-for="(gantt, index) in p.gantts"
                :key="index"
                @mouseenter="handleHover"
                @mouseleave="handleLeave"
              ></div>
            </div>
            <div class="children">
              <div class="row" v-for="child in p.children" :key="'child-' + child.pName">
                <div class="td">{{ child.pName }}</div>
                <div class="td">{{ child.startTime }}</div>
                <div class="td">{{ child.endTime }}</div>
                <div class="td" v-for="date in dateList" :key="date + 'grid-date'">
                  <div class="grids">
                    <div class="grid" v-for="day in getDays(date)" :key="'grid' + day.num" :ref="child.pName + '-' + day.date"></div>
                  </div>
                </div>
                <div
                  class="progress"
                  :style="gantt"
                  v-for="(gantt, index) in child.gantts"
                  :key="index"
                  @mouseenter="handleHover"
                  @mouseleave="handleLeave"
                ></div>
              </div>
            </div>
          </div>
        </div>
        <div class="tooltips" :style="tooltipsStyle">
          <div class="status">已逾期5天</div>
          <div class="charger">负责人：史蒂夫</div>
        </div>
      </div>
    </div>
  </Card>
</template>

<script>
import Card from '../components/Card.vue'
export default {
  components: { Card },
  props: {
    title: {
      type: String,
      default: ''
    }
  },
  created() {
    console.log(this.getDays('2022/09'), '到')
  },
  mounted() {
    this.setGantts()
  },
  data() {
    return {
      projects: [
        {
          pName: '地基与基础工程',
          startTime: '2020/04/06',
          endTime: '2020/05/09',
          delay: 10,
          status: 0,
          gantts: [],
          // gantts: [{ left: '420px', width: '100px', status: '' }],
          children: [
            { pName: '无支护土方工程', startTime: '2020/04/06', endTime: '2020/04/09', status: 1 },
            { pName: '有支护土方工程', startTime: '2020/04/10', endTime: '2020/05/08', status: 3 }
          ]
        },
        { pName: '主体结构', startTime: '2020/03/12', endTime: '2020/06/04', status: 2 },
        { pName: '建筑装饰装修', startTime: '2020/04/21', endTime: '2020/07/30', status: 1 }
      ],
      openedIndex: 9999,
      colors: ['#4C87FF', '#54CF8E', '#F2D026', '#FF6C7F'],
      tooltipsStyle: {
        display: 'none',
        left: 0,
        top: 0
      },
      scrollLeft: 0,
      scrollTimer: 0
    }
  },
  methods: {
    getGanttStyle(project) {
      let { startTime, endTime, pName } = project
      const startArr = startTime.split('/')
      const endArr = endTime.split('/')
      let startRef = null
      let endRef = null

      if (!(startArr[2] % 2)) {
        const day = startArr[2] - 1
        startArr[2] = day < 10 ? '0' + day : day
        startTime = startArr.join('/')
        console.log(startTime, 'xxx')
      }
      if (!(endArr[2] % 2)) {
        const day = endArr[2] - 1
        endArr[2] = day < 10 ? '0' + day : day
        endTime = endArr.join('/')
        console.log(endTime, 'xxx')
      }

      startRef = this.$refs[`${pName}-${startTime}`][0]
      const startLeft = startRef.offsetLeft

      endRef = this.$refs[`${pName}-${endTime}`][0]
      const endWidth = endRef.offsetWidth
      const endLeft = endRef.offsetLeft
      const ganttWidth = endLeft - startLeft + endWidth

      return { left: startLeft + 'px', width: ganttWidth + 'px' }
    },
    setGantts() {
      const configGantts = projects => {
        projects.map(project => {
          let { endTime, pName, gantts } = project
          const gantt = this.getGanttStyle(project)
          gantt.background = this.colors[project.status]

          if (gantts) {
            gantts.push(gantt)
          } else {
            project.gantts = [gantt]
          }

          if (project.delay) {
            const delayStartTime = this.increaseDate(endTime, 1)
            const delayEndTime = this.increaseDate(endTime, project.delay)
            const gantt = this.getGanttStyle({ startTime: delayStartTime, endTime: delayEndTime, pName })
            gantt.background = this.colors[3]
            gantts.push(gantt)
            console.log(gantt, '是的发生的范范')
          }

          // debugger
          project.children && configGantts(project.children)
        })
      }
      configGantts(this.projects)
    },
    increaseDate(date, delay) {
      const timestamp = new Date(date).getTime() + (delay + 1) * 1000 * 60 * 60 * 24
      return new Date(timestamp)
        .toISOString()
        .replace(/-/g, '/')
        .slice(0, 10)
    },
    getDays(date) {
      const year = date.split('/')[0]
      const month = +date.split('/')[1]
      const large = [1, 3, 5, 7, 8, 10, 12]
      const normal = [4, 6, 9, 11]
      const small = [2]
      let count = 0
      switch (true) {
        case large.includes(month):
          count = 31
          break
        case normal.includes(month):
          count = 30
          break
        case small.includes(month):
          count = year % 4 ? 28 : 29
          break
      }

      return (() => {
        const days = new Array(count)
          .fill(0)
          .map((item, index) => {
            let num = index + 1
            let fulldate = date + (num < 10 ? '/0' + num : '/' + num)
            return { num, date: fulldate }
          })
          .filter(item => item.num % 2)
        if (count === 28) {
          days.push({ num: 28, date: date + '/28' })
        } else if (count === 30) {
          days.push({ num: 30, date: date + '/30' })
        }
        return days
      })()
    },
    handleOpen(index) {
      if (index === this.openedIndex) {
        this.openedIndex = 9999
      } else {
        this.openedIndex = index
      }
    },
    handleScroll(e) {
      if (this.scrollTimer) {
        clearTimeout(this.scrollTimer)
      }
      this.scrollTimer = setTimeout(() => {
        this.scrollLeft = e.target.scrollLeft
        this.scrollTimer = null
      }, 100)
    },
    handleHover(e) {
      const { clientX, clientY } = e
      const decreaseLeft = clientX - 680
      const decreaseTop = clientY - 200
      this.tooltipsStyle = {
        left: decreaseLeft + this.scrollLeft + 'px',
        top: decreaseTop + 'px',
        display: 'block'
      }
    },
    handleLeave() {
      this.tooltipsStyle = {
        display: 'none'
      }
    }
  },
  computed: {
    dateList() {
      let dates = []
      const mapDates = data => {
        data.map(p => {
          dates.push(p.startTime)
          dates.push(p.endTime)
          p.children && mapDates(p.children)
        })
      }
      mapDates(this.projects)
      dates = dates.map(date => date.slice(0, 7)).sort()
      dates = [...new Set(dates)]
      return dates
    }
  }
}
</script>

<style lang="less" scoped>
.gantt-chart {
  height: 100%;
  .table {
    position: relative;
    height: 100%;
    overflow-x: auto;
    &::-webkit-scrollbar {
      width: 10px;
      height: 8px;
      cursor: pointer;
    }
    &::-webkit-scrollbar-thumb {
      border-radius: 10px;
      background-color: skyblue;
    }

    .thead {
      border-bottom: 1px solid #234d5f;
      .row {
        display: flex;
        .td {
          flex-shrink: 0;
          box-sizing: border-box;
          height: 42px;
          line-height: 42px;
          background-color: #163549;
          .date {
            line-height: 21px;
            border-left: 1px solid #234d5f;
            .month {
              border-bottom: 1px solid #234d5f;
            }
            .days {
              display: flex;
              .day {
                flex: 1;
              }
            }
          }
          &:nth-child(1) {
            padding-left: 40px;
            width: 200px;
          }
          &:not(:nth-child(1)) {
            width: 100px;
            text-align: center;
          }
          &:nth-child(n + 4) {
            width: 400px;
          }
        }
      }
    }
    .tbody {
      border-left: 1px solid #234d5f;
      .row-groups {
        position: relative;
        height: 42px;
        &::before {
          content: '';
          position: absolute;
          left: 26px;
          top: 16px;
          width: 0;
          height: 0;
          border-top: 4px solid transparent;
          border-right: 4px solid transparent;
          border-bottom: 4px solid transparent;
          border-left: 4px solid #5be1f4;
          z-index: 99;
        }
        &.open {
          height: unset;
          &::before {
            border-left-color: transparent;
            border-top-color: #5be1f4;
          }
        }
        > .row .td:first-child {
          user-select: none;
          cursor: pointer;
        }
        .row {
          position: relative;
          display: flex;
          .td {
            flex-shrink: 0;
            box-sizing: border-box;
            height: 42px;
            line-height: 42px;
            background-color: #0a1b2f;
            border-right: 1px solid #234d5f;
            border-bottom: 1px solid #234d5f;
            .grids {
              height: 100%;
              display: flex;
              .grid {
                position: relative;
                flex: 1;
                height: 100%;
                &:not(:last-child) {
                  border-right: 1px solid #234d5f;
                }
              }
            }
            &:nth-child(1) {
              padding-left: 40px;
              width: 200px;
            }
            &:not(:nth-child(1)) {
              width: 100px;
              font-size: 14px;
              text-align: center;
            }
            &:nth-child(n + 4) {
              width: 400px;
            }
          }
          .progress {
            flex-shrink: 0;
            position: absolute;
            top: calc(50% - 7px);
            width: 20px;
            height: 14px;
            background: #557dee;
          }
        }
        .children {
          .td {
            height: 38px;
            line-height: 38px;
            font-size: 14px;
          }
        }
      }
    }
    .tooltips {
      position: absolute;
      box-sizing: border-box;
      padding: 10px;
      width: 130px;
      height: 65px;
      font-size: 14px;
      color: #fff;
      border-radius: 8px;
      background-color: #50a6b3;
      .status {
        display: inline-block;
        margin-bottom: 6px;
        padding: 0 10px;
        height: 20px;
        min-width: 60px;
        line-height: 20px;
        font-size: 12px;
        border-radius: 10px;
        background-color: #ff6c7f;
      }
    }
  }
}
</style>
