vue实现时间段选择组件,分星期,最小粒度小时

<template>
  <div class="app-container">
    <div id="tim" class="byted-weektime">
      <div class="calendar">
        <div id="box">
          <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>
          <table class="calendar-table" style="width:800px">
            <thead class="calendar-head"><tr>
              <th rowspan="6" class="week-td">星期/时间</th>
              <th colspan="24">00:00 - 23:00</th>
            <tr>
              <td colspan="1" v-for="index in tableHeader">{{index}}</td>
            </tr>
            </thead>
            <tbody id="tableBody">
            <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>
    </div>
  </div>
</template>

<script>

export default {
  name: 'AppleTimmer',
  props: ['timmer'],
  data() {
    Array.prototype.remove = function(varElement)
    {
      var numDeleteIndex = -1;
      for (var i=0; i<this.length; i++)
      {
        // 严格比较,即类型与数值必须同时相等。
        if (this[i] === varElement)
        {
          this.splice(i, 1);
          numDeleteIndex = i;
          break;
        }
      }
      return numDeleteIndex;
    };
    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:[{"arr":[]},{"arr":[]},{"arr":[]},{"arr":[]},{"arr":[]},{"arr":[]},{"arr":[]}],
      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();
  },
  watch:{
    timmer(newValue,oldValue){
      if(newValue){
        this.timeContent = newValue;
        this.historyData();
      }

    },
  },
  mounted(){
    this.timeContent = this.timmer;
    this.viewData();
    var oBox = document.getElementById("tim");

    var oDiv = document.getElementById("kuang");
    //鼠标按下,获取初始点
    oBox.onmousedown = function (ev) {
      ev = window.event || ev;
      //1.获取按下的点
      var x1 = ev.pageX - $("#tim").offset().left;
      var y1 = ev.pageY - $("#tim").offset().top;
      oBox.onmousemove = function (ev) {
        ev = window.event || ev;
        var x2 = ev.pageX - $("#tim").offset().left;
        var y2 = ev.pageY - $("#tim").offset().top;
        //3.设置div的样式
        oDiv.style.left = ((x2 > x1 ? x1 : x2)-10) +"px";
        oDiv.style.top = ((y2 > y1 ? y1 : y2)-10) +"px";
        oDiv.style.width = (Math.abs(x2-x1))+"px";
        oDiv.style.height =(Math.abs(y2-y1))+"px";
      }
      oBox.onmouseup = function (ev) {
        oBox.onmousemove = null;
        oDiv.style.left = 0 +"px";
        oDiv.style.top = 0 +"px";
        oDiv.style.width = 0+"px";
        oDiv.style.height =0+"px";
      }
      return false;  //解除在划动过程中鼠标样式改变的BUG
    }
    document.onmouseup = function () {
      oBox.onmousemove = null;
    }
  },
  methods: {
    // 回显父组件传递过来的数据
    historyData(){
      this.timeContent = this.timmer;
      this.viewData();
      var oBox = document.getElementById("tim");

      var oDiv = document.getElementById("kuang");
    },
    init(){
      for (let i = 0; i < 7; i++) {
        let arr = []
        for (let j = 0; j < 24; 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.$emit('getTimmer',this.timeContent);
      }
      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])
          arr3.push(arr[arr.length-1])
          arr2.push(arr3)
        })
        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
      }
    },
    // 回显数据
    viewData(){
      for(let i=0;i<this.timeContent.length;i++){
        if(this.timeContent[i].arr.length > 0){
          let temp = this.timeContent[i].arr;
          for(let j=0;j<temp.length;j++){
            for(let z=0;z<=24;z++){
              if(z == temp[j]){
                this.rowUnit[i][z].class = 'ui-selected';
                break;
              }
            }
          }
        }
      }
    }
  }
}
</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;}
  #box{position: relative;}
</style>


引用处:

<AppleTimmer :timmer="timmer"/>

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值