基于vantUI的自定义范围的时间选择器

801 阅读1分钟

前言

某个定时需求中需要设置开始时间和结束时间,且顶部中间需要展示日期。

  • 开始时间:可设置当前时间后的24小时内的任一时间。
  • 结束时间:设置的开始时间后的24小时内的任一时间。 例:当前时间为11月16日18:25,开始时间设置范围为11月16日18:26分-11月17日18:25分。示例选择开始时间为11月16日21:00,结束时间可选范围为11月16日21:01-11月17日20:59。

微信截图_20211125170112.png

我们直接用代码说话吧~~

组件timerpicker.vue编写:

<template>
  <div class="timerPickerBox">
    <van-picker 
     v-if="show"
      show-toolbar
      :title="title" 
      :columns="columns"
      :default-index="defaultIndex"
      @confirm="confirm"
      @cancel="cancel"
      @change="change"
    />
  </div>
</template>
<script>
export default {
  name: "timepicker",
  data() {
    return {
      columns: [],
      defaultIndex: 0,
    }
  },
  props: {
    show: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: ''
    },
    minTime: {
      type: String,
      default: '00:00'
    },
    maxTime: {
      type: String,
      default: '23:59'
    },
    currentTime: {
      type: String,
      default: '00:00'
    }
  },
  mounted() {
    this.getColumns();
    this.showDefault();
  },
  computed: {
    timechange() {
      const { minTime, maxTime, currentTime } = this;
      return { minTime, maxTime, currentTime };
    }
  },
  watch: {
    timechange (newVal, oldVal) {
      this.getColumns();
      this.showDefault();
      this.columns = JSON.parse(JSON.stringify(this.columns))
    }
  },
  methods: {
    change(picker){
      this.$emit('change',picker)
    },
    cancel(){
      this.$emit('cancel')
    },
    confirm(val){
      this.$emit('confirm',val)
    },
    showDefault() {
      // 回显默认值
      let hour = this.currentTime.split(':')[0];
      let minute = this.currentTime.split(':')[1];
      console.log('hour= ',hour, ' minute= ',minute)
      let columnsCopy = JSON.parse(JSON.stringify(this.columns));
      let len = columnsCopy.length;
      if(len>1) {
        for(let index=0; index<len; index++) {
          let item = this.columns[index];
          if(parseInt(item.text)==parseInt(hour)) {
            this.defaultIndex = parseInt(index);
            if(item.children.length) {
              for(let i in item.children) {
                if(parseInt(item.children[i].text) == parseInt(minute)) {
                  item.defaultIndex = parseInt(i);
                  return false;
                }
              }
            }
          }
        }
      } else {
        this.defaultIndex = 0;
        if(parseInt(this.columns[0].text)==parseInt(hour)) {
          for(let i in this.columns[0].children) {
            if(parseInt(this.columns[0].children[i].text) == parseInt(minute)) {
              this.columns[0].defaultIndex = parseInt(i);
            }
          }
        } else {
          this.columns[0].defaultIndex = 0;
        }
      }
    },
    getColumns() {  
      let minTimeHour = parseInt(this.minTime.split(':')[0]);
      let minTimeMinute = parseInt(this.minTime.split(':')[1]);
      let maxTimeHour = parseInt(this.maxTime.split(':')[0]);
      let maxTimeMinute = parseInt(this.maxTime.split(':')[1]);
      if(minTimeHour<maxTimeHour || (minTimeHour == maxTimeHour && minTimeMinute <= maxTimeMinute)) {
        this.columns = this.getPartColumns(minTimeHour,maxTimeHour,minTimeMinute,maxTimeMinute);
      } else {
        let columns1 = this.getPartColumns(minTimeHour,23,minTimeMinute,59);
        let columns2 = this.getPartColumns(0,maxTimeHour,0,maxTimeMinute);
        this.columns = columns1.concat(columns2)
      }      
    },
    getPartColumns(minTimeHour,maxTimeHour,minTimeMinute,maxTimeMinute) {
      // console.log(minTimeHour,maxTimeHour,minTimeMinute,maxTimeMinute,'minTimeHour,maxTimeHour,minTimeMinute,maxTimeMinute')
      let minute = [{text: '00'},{text: '01'},{text: '02'},{text: '03'},{text: '04'},{text: '05'},{text: '06'},{text: '07'},{text: '08'},{text: '09'},
      {text: '10'},{text: '11'},{text: '12'},{text: '13'},{text: '14'},{text: '15'},{text: '16'},{text: '17'},{text: '18'},{text: '19'},
      {text: '20'},{text: '21'},{text: '22'},{text: '23'},{text: '24'},{text: '25'},{text: '26'},{text: '27'},{text: '28'},{text: '29'},
      {text: '30'},{text: '31'},{text: '32'},{text: '33'},{text: '34'},{text: '35'},{text: '36'},{text: '37'},{text: '38'},{text: '39'},
      {text: '40'},{text: '41'},{text: '42'},{text: '43'},{text: '44'},{text: '45'},{text: '46'},{text: '47'},{text: '48'},{text: '49'},
      {text: '50'},{text: '51'},{text: '52'},{text: '53'},{text: '54'},{text: '55'},{text: '56'},{text: '57'},{text: '58'},{text: '59'}];
      let hourArr = ['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23'];
      let partColumn = [];
      if(minTimeHour==maxTimeHour) {
        let hourItem = {text: hourArr[minTimeHour]};
        hourItem.children = minute.slice(minTimeMinute,maxTimeMinute+1)
        partColumn.push(hourItem)
      } else {
        for(let hour=minTimeHour; hour<maxTimeHour+1; hour++) {
          let hourItem = {text: hourArr[hour]}
          if(hour==minTimeHour) {
            hourItem.children = minute.slice(minTimeMinute,60)
          } else if(hour==maxTimeHour) {
            hourItem.children = minute.slice(0,maxTimeMinute+1)
          } else {
            hourItem.children = minute.slice(0,60)
          }
          partColumn.push(hourItem)
        }
      }
      return partColumn;
    },
  }
}
</script>
<style lang="less" scoped>
  /deep/.van-picker__title{
    overflow: auto;
    line-height: 44px;
    font-size: 32px;
    color: #2F3243;
  }
  /deep/.van-picker__toolbar{
    background-color: rgba(247,247,247,1);
    height:88px;
    line-height:88px;
    padding:0 30px;
  }
  // /deep/.van-picker__columns{
  //   height: 360px !important;
  // }
  // /deep/.van-picker-column__item,/deep/.van-picker__frame{
  //   height: 60px !important;
  // }
  /deep/.van-picker__cancel, /deep/.van-picker__confirm{
   font-size:28px !important;
  }
  /deep/.van-picker__cancel{
    color: #9BA3B0;
  }
  /deep/.van-picker__confirm{
    color: #2F3243;
  }
  /deep/.van-picker-column{
    color:#2F3243;
    font-size:36px !important;
  }
  /deep/.van-picker-column__item--selected{
    font-size:42px !important;
    color:#2F3243;
  }
  /deep/[class*=van-hairline]::after{
    border-top:1px solid rgba(155,163,176,1);
    border-bottom:1px solid rgba(155,163,176,1);
  }
</style>

该组件的使用示例:

<template>
  <div class="main">
    <van-popup v-model="showOnly" position="bottom" :overlay="true">
        <timerpicker
          :show="showOnly"
          :title="timeTitle"
          :minTime="minTime"
          :maxTime="maxTime"
          :currentTime="currentTime"
          @cancel="onTimeCancel"
          @confirm="onTimeConfirm"
          @change="onTimeChange"
        /> 
      </van-popup>
  </div>
</template>
<script>
import timerpicker from './timepicker.vue';
    export default {
      name: "addTime",
      data(){
          return{
            showOnly: false, // 仅一次 时间选择器
            listTime:[],
            text1:'未设置',
            text2:'未设置',
            isSelect:true,  // true 设置开启时间 false 设置关闭时间
            currentTime:'00:00',
            desc:'仅一次',
            weekDays:'0',
            device_id: '',
            obj:{},
            flag:'add',
            id: '',
            timeTitle: '',
            startTitle: '',
            curTitle: '',
            nextTitle: '',
            nnTitle: '',
            minTime: '00:00',
            maxTime: '23:59',
          }
      },
      components: { timerpicker },
      mounted(){
        const undisturbedDate = this.$store.state.undisturbedDate;
        this.desc = undisturbedDate.repeatDate || this.desc;
        this.weekDays = undisturbedDate.repeatStr || this.weekDays;
        this.text1 = undisturbedDate.startTime || this.text1;
        this.text2 = undisturbedDate.endTime || this.text2;
        this.device_id = undisturbedDate.device_id || '';
        this.flag = undisturbedDate.flag;
        this.id = undisturbedDate.id;
        // 设置时间选择器的显示日期
        this.setPickerDate();
        this.setOpenDate();
        this.setCloseDate();
      },
      methods:{  
        onTimeChange(picker){
          let pickerTime = picker.getValues();
          let pickerHour = pickerTime[0].text;
          let pickerMinute = pickerTime[1].text;  
          let curHours = new Date().getHours();
          let curMinutes = new Date().getMinutes();
          let startTime = this.text1.split(':');
          if(this.isSelect) {
            if(pickerHour > curHours || (pickerHour == curHours && pickerMinute > curMinutes)) {
              this.timeTitle = this.curTitle;
            } else {
              this.timeTitle = this.nextTitle;
            }
            this.startTitle = this.timeTitle;
          } else {
            if(pickerHour > startTime[0] || (pickerHour == startTime[0] && pickerMinute > startTime[1])) {
              this.timeTitle = this.startTitle;
            } else {
              if(this.startTitle==this.curTitle) {
                this.timeTitle = this.nextTitle;
              } else {
                this.timeTitle = this.nnTitle;
              }
            } 
          }
        },
        onTimeCancel(){
          this.showOnly=false;
        },
        onTimeConfirm(val){
          val = val[0] + ':' + val[1];
          if(this.isSelect){
            this.text1=val;
          }else{
            this.text2=val;
          }
          this.showOnly=false;
        },
        
        openDate(){ // 设置开启时间
          this.isSelect=true;
          if(this.text1!=='未设置'){
            this.currentTime=this.text1
          }else{
            this.currentTime='00:00'
          }
          if(this.desc=="仅一次") {
            // 设置时间选择器的显示日期
            this.setPickerDate();
            this.setOpenDate();
            // 设置时间选择器的可选时间范围
            let curDate = new Date();
            this.maxTime = curDate.getHours() + ':' + curDate.getMinutes(); 
            this.maxTime = this.addZero(this.maxTime);
            let afterMinute = new Date(curDate.getTime() + 60*1000); // 后一分钟
            this.minTime = afterMinute.getHours() + ':' + afterMinute.getMinutes(); 
            this.minTime = this.addZero(this.minTime);
            this.showOnly = true; 
          } else {
            this.show=true;
          }     
        },
        closeDate(){  // 设置关闭时间
          this.isSelect=false;
          if(this.text2!=='未设置'){
            this.currentTime=this.text2
          }else{
            this.currentTime='00:00'
          }
          if(this.desc=="仅一次") {  
            // 设置时间选择器的显示日期
            this.setPickerDate();
            this.setCloseDate();
            // 设置时间选择器的可选时间范围
            this.maxTime = this.text1
            let curDate = new Date();
            let startHour = this.text1.split(':')[0];
            curDate.setHours(startHour);
            curDate.setMinutes(startMinute);
            curDate = new Date(curDate);
            let newTime = new Date(curDate.getTime() + 60*1000); // 后一分钟
            this.minTime = newTime.getHours() + ':' + newTime.getMinutes(); 
            this.minTime = this.addZero(this.minTime);
            this.showOnly = true;
          } else {
            this.show=true;
          } 
        },
        // 更新当前三个日期
        setPickerDate() {
          let curDate = new Date();
          this.curTitle = curDate.getMonth()+1 + '月' + curDate.getDate() + '日';
          let nextDate = new Date(curDate.getTime() + 24*60*60*1000); //后一天
          this.nextTitle = nextDate.getMonth()+1 + '月' + nextDate.getDate() + '日';
          let nnDate = new Date(nextDate.getTime() + 24*60*60*1000); //后后一天
          this.nnTitle = nnDate.getMonth()+1 + '月' + nnDate.getDate() + '日';
        },
        // 设置开启时间的时间选择器的显示日期
        setOpenDate() {
          let curDate = new Date();
          let curHours = curDate.getHours();
          let curMinutes = curDate.getMinutes();
          let pickerTime = this.text1.split(':');
          if(pickerTime[0] > curHours || (pickerTime[0] == curHours && pickerTime[1] > curMinutes)) {
            this.timeTitle = this.curTitle;
          } else {
            this.timeTitle = this.nextTitle;
          } 
          this.startTitle = this.timeTitle;
          console.log('设置开启时间的时间选择器的显示日期 this.startTitle = ',this.startTitle)
        },
        // 设置关闭时间的时间选择器的显示日期
        setCloseDate() {
          let startTime = this.text1.split(':');
          let pickerTime = this.text2.split(':');
          if(pickerTime[0] > startTime[0] || (pickerTime[0] == startTime[0] && pickerTime[1] > startTime[1])) {
            this.timeTitle = this.startTitle;
          } else {
            if(this.startTitle==this.curTitle) {
              this.timeTitle = this.nextTitle;
            } else {
              this.timeTitle = this.nnTitle;
            }
          }
          console.log('设置关闭时间的时间选择器的显示日期 this.startTitle = ',this.timeTitle)
        },
        
     }
    }
</script>

若有不足之处,请不吝赐教喔 ~