问题:
在使用element-ui(vue2)时,发现
<el-time-select>支持选择固定的时间点但不支持传入可选时间端
<el-time-picker>支持传入可选时间段但不支持选择固定的时间点
自定义时间选择组件:
<template>
<el-select
class="custom-time-select"
v-model="innerValue"
:placeholder="placeholder"
filterable
@change="selectChange"
>
<el-option
v-for="(time, index) in filteredTimeList"
:key="index"
:label="time"
:value="time"
/>
</el-select>
</template>
<script>
export default {
name: 'CustomTimeSelect',
props: {
value: String,
start: {
type: String,
default: '08:00'
},
end: {
type: String,
default: '18:00'
},
step: {
type: String,
default: '00:30'
},
disabledRanges: {
// [{start: '14:00:00', end: '16:00:00'}]
type: Array,
default: () => []
},
placeholder: String
},
data() {
return {
timeList: [],
innerValue: this.value
};
},
computed: {
filteredTimeList() {
return this.timeList.filter(time => {
return !this.disabledRanges.some(range => {
return time >= range.start && time <= range.end;
});
});
}
},
watch: {
value(val) {
this.innerValue = val;
},
innerValue(val) {
this.$emit('input', val);
},
start: 'initTimeList',
end: 'initTimeList',
step: 'initTimeList',
disabledRanges: 'initTimeList'
},
mounted() {
this.initTimeList();
},
methods: {
initTimeList() {
this.timeList = [];
const [startH, startM] = this.start.split(':').map(Number);
const [endH, endM] = this.end.split(':').map(Number);
const [stepH, stepM] = this.step.split(':').map(Number);
let h = startH, m = startM;
while (h < endH || (h === endH && m <= endM)) {
const time = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
this.timeList.push(time);
m += stepM;
h += stepH + Math.floor(m / 60);
m %= 60;
}
},
selectChange(val) {
this.$emit('change', val);
}
}
};
</script>
<style scoped>
.custom-time-select {
width: 120px;
}
</style>
<el-form-item prop="time">
<CustomTimeSelect
v-model="Form.time"
:start="'08:00'"
:end="'22:00'"
:step="'00:30'"
:disabled-ranges="disabledRanges"
placeholder="请选择时间"
/>
</el-form-item>
其中, disabledRanges([{start: '14:00:00', end: '16:00:00'},...])就是需要禁用的时间段列表
如何需要实现的是时间段选择,还需要过滤非法的时间段,以下方式仅供参考:
<template>
<el-select
class="custom-time-select"
v-model="innerValue"
:placeholder="placeholder"
filterable
@change="selectChange"
>
<el-option
v-for="(time, index) in filteredTimeList"
:key="index" :label="time"
:value="time"
/>
</el-select>
</template>
<script>
export default {
name: 'CustomTimeSelect',
props: {
value: String,
start: { type: String, default: '08:00' },
end: { type: String, default: '18:00' },
step: { type: String, default: '00:30' },
disabledRanges: {
// [{start: '14:00:00', end: '16:00:00'}]
type: Array,
default: () => []
},
placeholder: String,
startTime: String
},
data() {
return {
timeList: [],
innerValue: this.value
};
},
computed: {
filteredTimeList() {
if (!this.startTime || !this.timeList.includes(this.startTime)) {
return this.timeList.filter(time => {
return !this.disabledRanges.some(range => {
return time >= range.start && time <= range.end;
});
});
}
const startIndex = this.timeList.indexOf(this.startTime);
let endIndex = this.timeList.length;
for (let range of this.disabledRanges) {
const rangeStartIndex = this.timeList.indexOf(range.start);
if (rangeStartIndex > startIndex) {
endIndex = rangeStartIndex;
break;
}
}
const filtered = this.timeList.slice(startIndex, endIndex);
if (!filtered.includes(this.innerValue)) {
this.$nextTick(() => {
this.innerValue = filtered[0];
this.$emit('input', filtered[0]);
this.$emit('change', filtered[0]);
});
}
return filtered;
}
},
watch: {
value(val) {
this.innerValue = val;
},
innerValue(val) {
this.$emit('input', val);
},
start: 'initTimeList',
end: 'initTimeList',
step: 'initTimeList',
disabledRanges: 'initTimeList',
startTime: 'initTimeList'
},
mounted() {
this.initTimeList();
},
methods: {
initTimeList() {
this.timeList = [];
const [startH, startM] = this.start.split(':').map(Number);
const [endH, endM] = this.end.split(':').map(Number);
const [stepH, stepM] = this.step.split(':').map(Number);
let h = startH, m = startM;
while (h < endH || (h === endH && m <= endM)) {
const time = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
this.timeList.push(time);
m += stepM;
h += stepH + Math.floor(m / 60);
m %= 60;
}
},
selectChange(val) {
this.$emit('change', val);
}
}
};
</script>
<style scoped>
.custom-time-select {
width: 120px;
}
</style>
<!-- 开始时间 -->
<el-form-item prop="startTime">
<CustomTimeSelect
v-model="Form.startTime"
:start="'08:00'"
:end="'22:00'"
:step="'00:30'"
:disabled-ranges="disabledRanges"
placeholder="开始时间"
/>
</el-form-item>
<span>至</span>
<!-- 结束时间 -->
<el-form-item prop="endTime">
<CustomTimeSelect
v-model="Form.endTime"
:start="Form.startTime || '08:00'"
:end="'22:00'"
:step="'00:30'"
:disabled-ranges="disabledRanges"
placeholder="请选择时间"
:start-time="Form.startTime"
/>
</el-form-item>
在结束时间组件中添加:start-time="Form.startTime"防止跨时间段选择