vue组件 -- 实现一种小时级时间段选择
效果操作大概是选择一个开始时间和一个结束时间(从左往右选是选择,从右往左是取消),排除已选后计算他们总的时间段。code<template><div><div class="hours-container"><div v-for="(item, index) in hours" :key="index" class="hours-item"><
·
效果
操作大概是选择一个开始时间和一个结束时间(从左往右选是选择,从右往左是取消),排除已选后计算他们总的时间段。
code
<template>
<div>
<div class="hours-container">
<div v-for="(item, index) in hours" :key="index" class="hours-item">
<div class="hours-item-header">{{ compItem(item) }}</div>
<div class="hours-item-value">
<div
:class="compClass(2 * item)"
@click="handleClick(2 * item)"
@mouseover="handleHover(2 * item)"
></div>
<div
:class="compClass(2 * item + 1)"
@click="handleClick(2 * item + 1)"
@mouseover="handleHover(2 * item + 1)"
></div>
</div>
</div>
</div>
<div class="tips">{{ tips }}</div>
</div>
</template>
<script>
/*
* @Description 为了实现24小时区间选择,若有星期的需求直接看 TimeRangeList组件
* @Author dengkangning
* @Date 2020年11月18日 16:33:19
*/
export default {
model: {
prop: "sendTimeList",
},
props: {
sendTimeList: {
required: true,
default: []
},
readonly: {
type: Boolean,
default: false
}
},
watch: {
timeRangeList: function (value) {
this.$emit('change', value);
this.$parent.$emit("el.form.change");// 触发父组件的校验规则
},
sendTimeList:{
handler () {
this.transformedIndex();
},
deep:true
}
},
computed: {
},
data() {
return {
hours: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22],// 选项
selectStart: false,// 开始
startIndex: '',// 开始下标
timeRangeList: [],// 选择的时间段
timeRangeListIndex: [],// 选中的下标
tempRangeIndex: [],// 预选下标
tips: '向右选中,向左取消选择'
}
},
methods: {
// 时间区间转换成下标区间
transformedIndex() {
this.timeRangeListIndex = [];
this.timeRangeList = this.sendTimeList;
this.timeRangeList.forEach(element => {
const [startTime, endTime] = element.match(/\d+\:\d+/g);
if (startTime && endTime) {
let [startHour, startMin] = startTime.split(':');
let [endHour, endMin] = endTime.split(':');
if (startHour && startMin && endHour && endMin) {
let startNum, endNum;
if (startMin === '00') {
startNum = 2 * parseInt(startHour);
} else {
startNum = 2 * parseInt(startHour) + 1;
}
if (endMin === '00') {
endNum = 2 * parseInt(endHour) - 1;
} else {
endNum = 2 * parseInt(endHour);
}
while (endNum >= startNum) {
this.timeRangeListIndex.push(startNum);
startNum++;
}
} else {
this.$message.error("时间段格式不正确");
}
} else {
this.$message.error("没有拿到开始时间或结束时间或者时间段格式不对");
}
});
this.tips = this.timeRangeList && this.timeRangeList.length > 0 ? this.timeRangeList : '向右选中,向左取消选择';
},
// 下标区间转换成时间区间
transformedSection() {
this.timeRangeList = [];
let startTime = '', endTime = '', len = this.hours.length;
for (let index = this.hours[0] * 2; index < 2 * (len + 1); index++) {
if (this.timeRangeListIndex.indexOf(index) > -1) {
if (startTime) {// 如果有开始时间,直接确定结束时间
let endHour = Math.floor((index + 1) / 2);
let endMin = (index + 1) % 2 === 0 ? "00" : "30";
endTime = `${endHour < 10 ? '0' + endHour : endHour}:${endMin}`;
} else {// 没有开始时间,确定当前点为开始时间
let startHour = Math.floor(index / 2);
let startMin = index % 2 === 0 ? "00" : "30";
startTime = `${startHour < 10 ? '0' + startHour : startHour}:${startMin}`;
}
if (index === 2 * this.hours.length + 1) { // 如果是最后一格,直接结束
endTime = `${Math.floor((index + 1) / 2)}:00`;
this.timeRangeList.push(`${startTime ? startTime : "23:30"}-${endTime}`);
startTime = '';
endTime = '';
}
} else { // 若这个点不在选择区间,确定一个时间段
if (startTime && endTime) {
this.timeRangeList.push(`${startTime}-${endTime}`);
startTime = '';
endTime = '';
} else if (startTime && !endTime) {// 这里可能只选半个小时
let endHour = Math.floor(index / 2);
let endMin = index % 2 === 0 ? "00" : "30";
endTime = `${endHour < 10 ? '0' + endHour : endHour}:${endMin}`;
this.timeRangeList.push(`${startTime}-${endTime}`);
startTime = '';
endTime = '';
}
}
}
this.tips = this.timeRangeList && this.timeRangeList.length > 0 ? this.timeRangeList : '向右选中,向左取消选择';
},
// 点击事件
handleClick(index) {
if (this.selectStart) {
if (index === this.startIndex) {// 双击取反
if (this.timeRangeListIndex.indexOf(index) > -1) {
this.timeRangeListIndex.splice(this.timeRangeListIndex.indexOf(index), 1);
} else {
this.timeRangeListIndex.push(this.startIndex);
}
} else if (index > this.startIndex) {// 选取数据--向右添加,向左取消
while (index >= this.startIndex) {
this.timeRangeListIndex.push(this.startIndex);
this.startIndex++;
}
this.timeRangeListIndex = Array.from(new Set(this.timeRangeListIndex));
} else {// 删除数据
while (this.startIndex >= index) {
if (this.timeRangeListIndex.indexOf(index) > -1) {
this.timeRangeListIndex.splice(this.timeRangeListIndex.indexOf(index), 1);
}
index++;
}
}
this.startIndex = '';
this.tempRangeIndex = [];
this.transformedSection();
} else {
this.startIndex = index;
}
this.selectStart = !this.selectStart;
},
// 预选区间
handleHover(index) {
if (this.selectStart) {
this.tempRangeIndex = [];
if (index > this.startIndex) {// 选取数据--向右添加,向左取消
while (index >= this.startIndex) {
this.tempRangeIndex.push(index);
index--;
}
} else {// 删除数据
while (this.startIndex >= index) {
this.tempRangeIndex.push(index);
index++;
}
}
}
},
// 是否选中,计算className
compClass(index) {
if (index === this.startIndex) {
return 'hours-item-left preSelected';
}
if (index >= this.startIndex) {
if (this.tempRangeIndex.indexOf(index) > -1) {
return 'hours-item-left preSelected';
}
} else {
if (this.tempRangeIndex.indexOf(index) > -1) {
return 'hours-item-left unSelected';
}
}
return this.timeRangeListIndex.indexOf(index) > -1 ? 'hours-item-left selected' : 'hours-item-left';
},
compItem(item) {// 不足10前面补0
return item < 10 ? `0${item}` : item;
},
},
mounted() {
this.transformedIndex();
}
}
</script>
<style lang="scss" scoped>
.hours-container {
display: flex;
cursor: pointer;
.hours-item {
width: 30px;
height: 60px;
border: 1px solid #c2d0f3;
border-right: none;
text-align: center;
&:last-child {
border-right: 1px solid #c2d0f3;
}
.hours-item-header {
width: 100%;
height: 30px;
line-height: 30px;
border-bottom: 1px solid #c2d0f3;
}
.hours-item-value {
width: 100%;
height: 30px;
box-sizing: border-box;
display: flex;
.hours-item-left,
.hours-item-right {
width: 50%;
height: 100%;
border-right: 1px solid #c2d0f3;
box-sizing: border-box;
&:last-child {
border-right: none;
}
}
}
.selected {
background-color: #4e84fe;
border-bottom: 1px solid #c2d0f3;
}
.preSelected {
background-color: #8eaffc;
border-bottom: 1px solid #c2d0f3;
}
.unSelected {
background-color: #ffffff;
border-bottom: 1px solid #c2d0f3;
}
}
}
.tips {
width: 100%;
line-height: 30px;
}
</style>
更多推荐
已为社区贡献1条内容
所有评论(0)