vue2实现时间拖拽选择器

<template>
  <div class="byted-weektime">
    <div class="calendar">
      <!-- <div class="schedule"></div> -->
      <!-- <div class="schedule" style="opacity: 0; display: none; left: 680px; top: 294px; width: 11px; height: 30px;"></div> -->
      <table class="calendar-table" style="width:810px">
        <thead class="calendar-head">
          <tr>
            <th rowspan="10" class="week-td">星期/时间</th>
            <th colspan="12">00:00 - 06:00</th>
            <th colspan="12">06:00 - 12:00</th>
            <th colspan="12">12:00 - 18:00</th>
            <th colspan="12">18:00 - 24:00</th>
          </tr>
          <!-- <tr>
            <td colspan="2" v-for="index in tableHeader">{{ index }}</td>
          </tr> -->
        </thead>
        <tbody @mousemove.prevent.stop="kuangMove" @mouseleave.prevent.stop="kuangLeave" @mousedown.prevent.stop="kuangDown" @mouseup.prevent.stop="kuangUp">
        <!-- 不画框,没bug -->
        <!-- <tbody id="tableBody"> -->
          <div id="kuang"
            :style="{ width: kuangObj.width + 'px', height: kuangObj.height + 'px', top: kuangObj.top + 'px', left: kuangObj.left + 'px', bottom: kuangObj.bottom + 'px', right: kuangObj.right + 'px' }">
          </div>
          <tr>
            <td>星期一</td>
            <td @mousedown.prevent="handleMouseDown(i, 0)" @mouseup.prevent="handleMouseUp(i, 0)"
              class="calendar-atom-time" :class="item.class" v-for="(item, i) in rowUnit[0]"></td>
          </tr>
          <tr>
            <td>星期二</td>
            <td @mousedown.prevent="handleMouseDown(i, 1)" @mouseup.prevent="handleMouseUp(i, 1)"
              class="calendar-atom-time" :class="item.class" v-for="(item, i) in rowUnit[1]"></td>
          </tr>
          <tr>
            <td>星期三</td>
            <td @mousedown.prevent="handleMouseDown(i, 2)" @mouseup.prevent="handleMouseUp(i, 2)"
              class="calendar-atom-time" :class="item.class" v-for="(item, i) in rowUnit[2]"></td>
          </tr>
          <tr>
            <td>星期四</td>
            <td @mousedown.prevent="handleMouseDown(i, 3)" @mouseup.prevent="handleMouseUp(i, 3)"
              class="calendar-atom-time" :class="item.class" v-for="(item, i) in rowUnit[3]"></td>
          </tr>
          <tr>
            <td>星期五</td>
            <td @mousedown.prevent="handleMouseDown(i, 4)" @mouseup.prevent="handleMouseUp(i, 4)"
              class="calendar-atom-time" :class="item.class" v-for="(item, i) in rowUnit[4]"></td>
          </tr>
          <tr>
            <td>星期六</td>
            <td @mousedown.prevent="handleMouseDown(i, 5)" @mouseup.prevent="handleMouseUp(i, 5)"
              class="calendar-atom-time" :class="item.class" v-for="(item, i) in rowUnit[5]"></td>
          </tr>
          <tr>
            <td>星期日</td>
            <td @mousedown.prevent="handleMouseDown(i, 6)" @mouseup.prevent="handleMouseUp(i, 6)"
              class="calendar-atom-time" :class="item.class" v-for="(item, i) in rowUnit[6]"></td>
          </tr>
 
          <tr>
            <td colspan="49" class="td-table-tip">
              <div class="clearfix">
                <span class="pull-left tip-text">请用鼠标点选时间段</span> <a @click="clear" class="pull-right"> 清空</a>
              </div>
            </td>
          </tr>
          <tr>
            <td colspan="49" class="timeContent">
              <div v-for="(item, index) in timeStr" v-show="item.length">
                <span>{{ weekDate[index + 1] }}: </span>
                <strong><span>{{ item }}</span></strong>
              </div>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>
 
<script>
export default {
  name: 'timeSelect',
  data() {
    return {
      // tableHeader: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'],
      weekDate: { '1': '星期一', '2': '星期二', '3': '星期三', '4': '星期四', '5': '星期五', '6': '星期六', '7': '星期日' },
      rowUnit: [ //每一个单元格
      ],
      timeContent: [ //选中的时间段原始数据
      ],
      timeSection: [  //时间段,可以返回给后端的数据
      ],
      timeStr: [    //时间段,前端显示的数据
      ],
      beginDay: 0,
      beginTime: 0,
      downEvent: false,
      kuangObj: {
        width: 0,
        height: 0,
        top: 0,
        left: 0,
        bottom: 0,
        right: 0,
        oldLeft: 0,
        oldTop: 0,
        flag: false
      }
    }
  },
  created() {
    this.init()
  },
  mounted() {
  },
  methods: {
    init() {
      for (let i = 0; i < 7; i++) {
        let arr = []
        for (let j = 0; j < 48; j++) {
          arr.push({ class: null, timeData: j })
        }
        this.rowUnit.push(arr)
        this.timeContent.push({ arr: [] })
        this.timeSection.push([])
        this.timeStr.push('')
      }
    },
    handleMouseDown(i, day) {
      this.downEvent = true //按下时鼠标不在范围内则不算
      this.beginDay = day
      this.beginTime = i
    },
    handleMouseUp(i, day) {
      //当点击事件是在table内才触发选取数据操作
      if (this.downEvent) {
        //选时间段
        let _this = this
        let begin = this.beginTime
        let start = begin <= i ? begin : i //x轴 起点
        let length = Math.abs(begin - i)
        let end = start + length           //x轴 终点
        let dayStart = this.beginDay <= day ? this.beginDay : day //y轴 起点
        let dayLength = Math.abs(this.beginDay - day)
        let dayEnd = dayStart + dayLength                         //y轴 终点
        //当框选范围内所有块都是选中状态时,执行反选
        function isAdd() {
          for (let x = dayStart; x < dayEnd + 1; x++) {
            for (let y = start; y < end + 1; y++) {
              if (_this.rowUnit[x][y].class == null) return true
            }
          }
          return false
        }
        if (isAdd()) {
          //没选中的全都选上
          for (let x = dayStart; x < dayEnd + 1; x++) {
            for (let y = start; y < end + 1; y++) {
              if (this.rowUnit[x][y].class == null) {
                this.rowUnit[x][y].class = 'ui-selected'
                this.timeContent[x].arr.push(this.rowUnit[x][y].timeData)
              }
            }
          }
        } else { //反选
          for (let x = dayStart; x < dayEnd + 1; x++) {
            for (let y = start; y < end + 1; y++) {
              this.rowUnit[x][y].class = null
              this.timeContent[x].arr.remove(this.rowUnit[x][y].timeData)
            }
          }
        }
        //过滤时间段,将临近的时间段合并
        this.filterTime(dayStart, dayEnd)
      }
      this.downEvent = false
    },
    filterTime(start, end) {  //选中的x,y坐标信息 x:0-47  y:0-6
      function sortCut(arr) {  //提取连续的数字
        var result = []
        arr.forEach(function (v, i) {
          var temp = result[result.length - 1];
          if (!i) {
            result.push([v]);
          } else if (v % 1 === 0 && v - temp[temp.length - 1] == 1) {
            temp.push(v)
          } else {
            result.push([v])
          }
        });
        return result
      }
      function toStr(num) {
        if (Number.isInteger(num)) {
          let str = num < 10 ? ('0' + num) : num.toString()
          return str + ':00'
        } else {
          let str = Math.floor(num) < 10 ? ('0' + Math.floor(num)) : Math.floor(num).toString()
          return str + ':30'
        }
      }
      function timeToStr(arr) {  //把数组转成方便人看到字符串
        let str = ''
        arr.forEach((arr, index) => {
          let str1 = ''
          if (index == 0) {
            str1 = toStr(arr[0]) + '~' + toStr(arr[1])
          } else {
            str1 = ' , ' + toStr(arr[0]) + '~' + toStr(arr[1])
          }
          str += str1
        })
        return str
      }
      //排序,分割成
      for (let i = start; i < end + 1; i++) {
        let arr1 = sortCut(this.timeContent[i].arr.sort((a, b) => a - b))
        let arr2 = []
        arr1.forEach((arr) => {   //转成带小数点的时间段,以及供前端显示的字符串
          let arr3 = []
          arr3.push(arr[0] / 2)
          arr3.push(arr[arr.length - 1] / 2 + 0.5)
          arr2.push(arr3)
        })
        //console.log(arr2)
        this.timeStr[i] = timeToStr(arr2)
        this.timeSection[i] = arr2
      }
    },
    clear() {
      this.rowUnit.forEach((item) => {
        item.forEach((item1) => {
          item1.class = null
        })
      })
      this.timeContent.forEach((item) => {
        item.arr = []
      })
      this.timeSection.forEach((item) => {
        //赋值成空数组[]出问题
        item.length = 0
      })
      //遍历赋值成'',不管用
      this.timeStr.length = 0
      for (let i = 0; i < 7; i++) {
        this.timeStr.push('')
      }
      //this.initState = true
    },
    //画框操作
    kuangMove() {
      if (!this.kuangObj.flag) return
      if (this.downEvent) {
        let x1 = this.kuangObj.oldLeft
        let y1 = this.kuangObj.oldTop
        let x2 = event.layerX
        let y2 = event.layerY
        this.kuangObj.left = (x2 > x1 ? x1 : x2)
        this.kuangObj.top = (y2 > y1 ? y1 : y2)
        this.kuangObj.width = Math.abs(x2 - x1)
        this.kuangObj.height = Math.abs(y2 - y1)
      }
    },
    kuangDown() {
      this.kuangObj.flag = true
      this.kuangObj.oldLeft = event.layerX
      this.kuangObj.oldTop = event.layerY
    },
    kuangUp() {
      this.kuangObj.flag = false
      this.clearDragData()
    },
    kuangLeave() {
      this.kuangObj.flag = false
      this.clearDragData()
    },
    clearDragData() {
      for (let prop in this.kuangObj) {
        this.kuangObj[prop] = 0
      }
    }
  }
}
 
</script>
 
<style scoped>
.byted-weektime .calendar {
  -webkit-user-select: none;
  position: relative;
  display: inline-block
}
 
/*.byted-weektime .calendar .schedule{background:#2F88FF;width:0;height:0;position:fixed;display:none;top:0;left:0;pointer-events:none;-webkit-transition:all 400ms ease;-moz-transition:all 400ms ease;-ms-transition:all 400ms ease;transition:all 400ms ease}*/
.byted-weektime .calendar .calendar-table {
  border-collapse: collapse;
  border-radius: 4px
}
 
.byted-weektime .calendar .calendar-table tr .calendar-atom-time:hover {
  background: #ccc
}
 
.byted-weektime .calendar .calendar-table tr .ui-selected {
  background: #2F88FF
}
 
.byted-weektime .calendar .calendar-table tr .ui-selected:hover {
  background: #2F88FF
}
 
.byted-weektime .calendar .calendar-table tr,
.byted-weektime .calendar .calendar-table td,
.byted-weektime .calendar .calendar-table th {
  border: 1px solid #ccc;
  font-size: 12px;
  text-align: center;
  min-width: 11px;
  line-height: 1.8em;
  -webkit-transition: background 200ms ease;
  -moz-transition: background 200ms ease;
  -ms-transition: background 200ms ease;
  transition: background 200ms ease
}
 
.byted-weektime .calendar .calendar-table tbody tr {
  height: 30px
}
 
.byted-weektime .calendar .calendar-table tbody tr td:first-child {
  background: #F8F9FA
}
 
.byted-weektime .calendar .calendar-table thead th,
.byted-weektime .calendar .calendar-table thead td {
  background: #F8F9FA
}
 
.byted-weektime .calendar .calendar-table .td-table-tip {
  line-height: 2.4em;
  padding: 0 12px 0 19px;
  background: #fff !important
}
 
.byted-weektime .calendar .calendar-table .td-table-tip .clearfix {
  height: 46px;
  line-height: 46px
}
 
.byted-weektime .calendar .calendar-table .td-table-tip .pull-left {
  font-size: 14px;
  color: #333333
}
 
.byted-weektime .week-td {
  width: 75px;
  padding: 20px 0
}
 
.byted-weektime a {
  cursor: pointer;
  color: #2F88FF;
  font-size: 14px
}
 
#kuang {
  position: absolute;
  background-color: blue;
  opacity: 0.3;
}
</style>
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值