我是靠谱客的博主 要减肥狗,最近开发中收集的这篇文章主要介绍用a-time-picker写一个时间范围选择器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

起因

使用过ant-design组件库的人基本都知道,它的time-picker组件并不像date-picker组件那样,支持时间范围选择。所以,这个时候就只能自己手动来写一个了。

效果

当都为空时可校验
image.png
选择时如果先填写开始时间,则结束时间框前面置灰
image.png
选择时如果先填写结束时间,则开始时间框后面置灰
image.png

实现思路

其中最关键的是如果限制时间范围不冲突,也就是开始时间一定要早于结束时间,其中包含时,分,秒

这里可以利用原生组件的几个方法:
image.png

这里因为只需要选择时和分,所以先只有时、分的选项进行验证。

<template>
    <div class="cb">
       <span class="cur-p mr20" @click="addTime(item.id)">添加时间段</span>
    </div>
    <a-modal width="830px" title="考场时间段管理" class="common-modal"
    :footer="null" :maskClosable="false" :visible.sync="timeShow" @cancel="resetTimeShow">
      <a-form-model v-if="timeShow" class="label110" ref="ExamTimeRef" :model="timeInfo">
        <a-form-model-item label="考试时间段" required>
          <div class="flex">
            <a-form-model-item class="wd308" :rules="rules.isDate" prop="startTime">
              <a-time-picker
                :disabled="disabled"
                format="HH:mm"
                :disabledHours="getDisabledBeginHours"
                :disabledMinutes="getDisabledBeginMinutes"
                :value="timeInfo && timeInfo.startTime ? $moment(timeInfo.startTime, 'HH:mm') : null"
                placeholder="开始时间"
                @change="startTimeChange">
              </a-time-picker>
            </a-form-model-item>
            <div class="ml5 mr5">至</div>
            <a-form-model-item class="wd308" :rules="rules.isDate" prop="endTime">
              <a-time-picker
                :disabled="disabled"
                format="HH:mm"
                :value="timeInfo && timeInfo.endTime ? $moment(timeInfo.endTime, 'HH:mm') : null"
                placeholder="结束时间"
                :disabledHours="getDisabledEndHours"
                :disabledMinutes="getDisabledEndMinutes"
                @change="endTimeChange">
              </a-time-picker>
            </a-form-model-item>
          </div>
        </a-form-model-item>
      </a-form-model>
      <div class="vr mt20">
        <a-button class="mr20" @click="resetTimeShow">取消</a-button>
        <a-button type="primary" @click="saveExamTime">确定</a-button>
      </div>
    </a-modal>
  </div>
</template>
<script>
  import { validator, validCallback } from '@/utils'
  export default {
    data() {
      return {
        rules: validator,
        timeShow: false,
        timeInfo:{
          startTime:undefined,
          endTime:undefined,
        },
        disabled:false
      }
    },
    methods: {
      async addTime(id){
        this.timeShow = true
        this.timeInfo.examRoomId = id
      },
      resetTimeShow(){ //关闭弹框数据重置
        this.timeShow = false
        this.disabled = false
        this.timeInfo = {
          startTime: undefined,
          endTime:undefined
        }
      },
      saveExamTime () {
        validCallback(this, 'ExamTimeRef', _ => {
          let _timeInfo = this.timeInfo
          let _params = {
            startTime: _timeInfo.startTime,
            endTime: _timeInfo.endTime,
          }
          saveExaTimeApi(_params).then(res => {
            cbSuccess(res.data, _ => {
              this.resetTimeShow()
            })
          })
        })
      },
      editTime(row){
        this.timeInfo = JSON.parse(JSON.stringify(row))
        this.timeInfo.startTime = this.$moment(this.timeInfo.startTime, 'HH:mm')
        this.timeInfo.endTime = this.$moment(this.timeInfo.endTime, 'HH:mm')
        this.timeShow = true
      },
      startTimeChange (time, timeString) {
        this.timeInfo.startTime = timeString
      },
      endTimeChange (time, timeString) {
        this.timeInfo.endTime = timeString
      },
      getDisabledBeginHours () {
        const hours = []
        // 排除当前时间段比结束时间还晚的小时
        if (this.timeInfo.endTime) {
          const timeArr = this.timeInfo.endTime.split(':')
          if (timeArr.length > 1) {
            for (let i = parseInt(timeArr[0]) + 1; i < 24; i++) {
              hours.push(i) // 排除比当前时间段的结束时间同一个小时下更晚的分钟
            }
          }
        }
        return hours
      },
      getDisabledBeginMinutes (selectedHour) {
        const minutes = []
        if(this.timeInfo.endTime){
          const timeArr = this.timeInfo.endTime.split(':')
          if (timeArr.length > 1) {
            if (selectedHour === parseInt(timeArr[0])) {
              for (var i = parseInt(timeArr[1]) + 1; i < 60; i++) {
                minutes.push(i)
              }
            }
          }
          return minutes
        }
      },
      getDisabledEndHours () {
        const hours = []
        // 排除当前时间段比开始时间还早的小时
        if (this.timeInfo.startTime) {
          const timeArr = this.timeInfo.startTime.split(':')
          if (timeArr.length > 1) {
            for (let i = 0; i < parseInt(timeArr[0]); i++) {
              hours.push(i)
            }
          }
        }
        return hours
      },
      getDisabledEndMinutes (selectedHour) {
        const minutes = []
        if(this.timeInfo.startTime){
          const timeArr = this.timeInfo.startTime.split(':')
          if (timeArr.length > 1) {
            if (selectedHour === parseInt(timeArr[0])) {
              for (var i = 0; i < parseInt(timeArr[1]) + 1; i++) {
                minutes.push(i)
              }
            }
          }
          return minutes
        }
      },
    },
  }
</script>

以上四个方法(getDisabledBeginHours、getDisabledBeginMinutes、getDisabledEndHours、getDisabledEndMinutes)分别对开始时间的时和分,结束时间的时和分的选项是否禁用进行验证和过滤。

最后是利用change事件(startTimeChange、endTimeChange)把选择的时间同步到data中

补充一下校验双空的方法validater.js

// 校验ant中日期、时间为空
export const validator = {
  isDate: {
    required: true,
    message: '必填项',
    trigger: ['change']
  },
}

export function defineValidator (validator, type) {
  type = type || ['blur', 'change']
  return { required: true, validator: validator, trigger: type }
}

下面是一个分割线,如果只有一个地方用到时间选择器,看到这里就行了。
如果多个地方用到时间范围选择器,就需要封装一个组件,那么请继续往下看。
考虑到如果是要选择一天内的多个时间段,且时间段之间不能冲突,那么代码就要做一点修改了。

定义一些prop属性


props: {
    // 时间显示格式
    timeFormat: {
      type: String,
      default: 'HH:mm'
    },
    // 组件绑定的值
    timeData: {
      type: Object,
      default: function () {
        return null
      }
    },
    // 如果是有多段时间选择,此变量为所有时间段的时间数据
    timeDatas: {
      type: Array,
      default: function () {
        return []
      }
    },
    // 组件是否需要禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 未选择时间时组件显示的内容
    placeholder: {
      type: Array,
      default: function () {
        return []
      }
    },
    // 开始时间和结束时间是否需要展示更宽的宽度
    wider: {
      type: Boolean,
      default: false
    }
  },

封装的组件的核心代码

<div style="display: inline-block;">
    <a-time-picker
      :disabled="disabled"
      :style="(wider ? 'width: 165px;margin-right: 10px' : 'width: 128px;margin-right: 10px')"
      :format="timeFormat"
      :disabledHours="getDisabledBeginHours"
      :disabledMinutes="getDisabledBeginMinutes"
      :value="timeData && timeData.timeBegin ? moment(timeData.timeBegin, timeFormat) : null"
      :placeholder="placeholder[0]"
      @change="startTimeChange"></a-time-picker>
    <a-time-picker
      :style="(wider ? 'width: 165px' : 'width: 128px')"
      :disabled="disabled"
      :format="timeFormat"
      :value="timeData && timeData.timeEnd ? moment(timeData.timeEnd, timeFormat) : null"
      :placeholder="placeholder[1]"
      :disabledHours="getDisabledEndHours"
      :disabledMinutes="getDisabledEndMinutes"
      @change="endTimeChange"></a-time-picker>
  </div>

注意: 下面代码时间对象timeData中的id是number

getDisabledBeginHours () {
      const hours = []
      // 排除当前时间段比结束时间还晚的小时
      if (this.timeData) {
        const timeArr = this.timeData.timeEnd.split(':')
        if (timeArr.length > 1) {
          for (let i = parseInt(timeArr[0]) + 1; i < 24; i++) {
            hours.push(i) // 排除比当前时间段的结束时间同一个小时下更晚的分钟
          }
        }
      }
      // 排除比前面的时间段更晚早的小时
      if (this.timeDatas) {
        const earlierTime = []
        const laterTime = []
        this.timeDatas.forEach(t => {
          if (t.id > this.timeData.id) {
            laterTime.push(t) // 获取更晚的时间段
          } else if (t.id < this.timeData.id) {
            earlierTime.push(t) // 获取更早的时间段
          }
        })
        if (earlierTime.length > 0) {
          const timeArr = earlierTime[earlierTime.length - 1].timeEnd.split(':')
          if (timeArr.length > 1) {
            for (let i = 0; i < parseInt(timeArr[0]); i++) {
              hours.push(i) // 排除比更早的最后一个时间段的结束时间的更小的小时
            }
          }
        }
        if (laterTime.length > 0) {
          const timeArr = laterTime[0].timeBegin.split(':')
          if (timeArr.length > 1) {
            for (let i = parseInt(timeArr[0]) + 1; i < 24; i++) {
              hours.push(i) // 排除比更晚的第一个时间段的开始时间的更大的小时
            }
          }
        }
      }
      return hours
    },
    getDisabledBeginMinutes (selectedHour) {
      const minutes = []
      const timeArr = this.timeData.timeEnd.split(':')
      if (timeArr.length > 1) {
        if (selectedHour === parseInt(timeArr[0])) {
          for (var i = parseInt(timeArr[1]) + 1; i < 60; i++) {
            minutes.push(i)
          }
        }
      }
      // 排除比前面的时间段更晚早的分钟
      if (this.timeDatas) {
        const earlierTime = []
        const laterTime = []
        this.timeDatas.forEach(t => {
          if (t.id > this.timeData.id) {
            laterTime.push(t) // 获取更晚的时间段
          } else if (t.id < this.timeData.id) {
            earlierTime.push(t) // 获取更早的时间段
          }
        })
        if (earlierTime.length > 0) {
          const timeArr = earlierTime[earlierTime.length - 1].timeEnd.split(':')
          if (timeArr.length > 1) {
            if (selectedHour === parseInt(timeArr[0])) {
              for (let i = 0; i < parseInt(timeArr[1]) + 1; i++) {
                minutes.push(i) // 排除比更早的最后一个时间段的结束时间同一个小时的更小的分钟
              }
            }
          }
        }
        if (laterTime.length > 0) {
          const timeArr = laterTime[0].timeBegin.split(':')
          if (timeArr.length > 1) {
            if (selectedHour === parseInt(timeArr[0])) {
              for (let i = parseInt(timeArr[1]) + 1; i < 60; i++) {
                minutes.push(i) // 排除比更晚的第一个时间段的开始时间同一个小时的更大的分钟
              }
            }
          }
        }
      }
      return minutes
    },
    getDisabledEndHours () {
      const hours = []
      // 排除当前时间段比开始时间还早的小时
      if (this.timeData) {
        const timeArr = this.timeData.timeBegin.split(':')
        if (timeArr.length > 1) {
          for (let i = 0; i < parseInt(timeArr[0]); i++) {
            hours.push(i)
          }
        }
      }
      // 排除比后面的时间段更晚的小时
      if (this.timeDatas) {
        const laterTime = []
        const earlierTime = []
        this.timeDatas.forEach(t => {
          if (t.id > this.timeData.id) {
            laterTime.push(t) // 获取更晚的时间段
          } else if (t.id < this.timeData.id) {
            earlierTime.push(t) // 获取更早的时间段
          }
        })
        if (earlierTime.length > 0) {
          const timeArr = earlierTime[earlierTime.length - 1].timeEnd.split(':')
          if (timeArr.length > 1) {
            for (let i = 0; i < parseInt(timeArr[0]); i++) {
              hours.push(i) // 排除比更早的最后一个时间段的结束时间的更小的小时
            }
          }
        }
        if (laterTime.length > 0) {
          const timeArr = laterTime[0].timeBegin.split(':')
          if (timeArr.length > 1) {
            for (let i = parseInt(timeArr[0]) + 1; i < 24; i++) {
              hours.push(i) // 排除比更晚的第一个时间段的开始时间更大的小时
            }
          }
        }
      }
      return hours
    },
    getDisabledEndMinutes (selectedHour) {
      const minutes = []
      const timeArr = this.timeData.timeBegin.split(':')
      if (timeArr.length > 1) {
        if (selectedHour === parseInt(timeArr[0])) {
          for (var i = 0; i < parseInt(timeArr[1]) + 1; i++) {
            minutes.push(i)
          }
        }
      }
      // 排除比后面的时间段更晚的分钟
      if (this.timeDatas) {
        const laterTime = []
        const earlierTime = []
        this.timeDatas.forEach(t => {
          if (t.id > this.timeData.id) {
            laterTime.push(t) // 获取更晚的时间段
          } else if (t.id < this.timeData.id) {
            earlierTime.push(t) // 获取更早的时间段
          }
        })
        if (earlierTime.length > 0) {
          const timeArr = earlierTime[earlierTime.length - 1].timeEnd.split(':')
          if (timeArr.length > 1) {
            if (selectedHour === parseInt(timeArr[0])) {
              for (let i = 0; i < parseInt(timeArr[1]); i++) {
                minutes.push(i) // 排除比更早的最后一个时间段的结束时间的同一个小时更小的分钟
              }
            }
          }
        }
        if (laterTime.length > 0) {
          const timeArr = laterTime[0].timeBegin.split(':')
          if (timeArr.length > 1) {
            if (selectedHour === parseInt(timeArr[0])) {
              for (let i = parseInt(timeArr[1]) + 1; i < 60; i++) {
                minutes.push(i) // 排除比更晚的第一个时间段的开始时间的同一个小时更大的分钟
              }
            }
          }
        }
      }
      return minutes
    },

最后是利用change事件,把change之后的时间传递给父组件

startTimeChange (time, timeString) {
   this.$emit('startTimeChange', this.timeData, timeString)
},
endTimeChange (time, timeString) {
    this.$emit('endTimeChange', this.timeData, timeString)
}

最后

以上就是要减肥狗为你收集整理的用a-time-picker写一个时间范围选择器的全部内容,希望文章能够帮你解决用a-time-picker写一个时间范围选择器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部