概述
起因
使用过ant-design组件库的人基本都知道,它的time-picker组件并不像date-picker组件那样,支持时间范围选择。所以,这个时候就只能自己手动来写一个了。
效果
当都为空时可校验
选择时如果先填写开始时间,则结束时间框前面置灰
选择时如果先填写结束时间,则开始时间框后面置灰
实现思路
其中最关键的是如果限制时间范围不冲突,也就是开始时间一定要早于结束时间,其中包含时,分,秒
这里可以利用原生组件的几个方法:
这里因为只需要选择时和分,所以先只有时、分的选项进行验证。
<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写一个时间范围选择器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复