选择上午、下午时间段并得总共时长弹出框组件_Vue

在现代Web应用中,用户界面的友好性和交互性至关重要,特别是在处理时间选择这类常见功能时。本文将详细介绍如何利用Vue.js框架结合微信小程序(uni-app)开发一个自定义的时间段选择组件。这个组件允许用户便捷地选择上午或下午的具体时间段,并计算所选时间段的总工作时长。

组件概述

本组件通过弹出层(u-popup)展示,提供了上午和下午两个时段的选择,每个时段内有预设的开始时间选项。用户点击不同的时间选项后,组件会自动计算并显示所选时间段的工作小时数。最后,用户确认选择后,组件通过事件向外传递所选的开始时间、结束时间和总工作时长。

技术栈

  • Vue.js:前端框架,用于构建组件的结构和逻辑。
  • uni-app:基于Vue.js的跨平台开发框架,支持微信小程序等多端开发。
  • SCSS:CSS预处理器,增强样式编写能力。
<template>
	<u-popup :show="show" mode="bottom"  @close="close" @open="open" :closeable="true">
		<view class="">
			<view class="title">选择服务时间 </view> 
			
			<view class="workTime">
				<view class="t1" @click="choseType('am')">{{startTime}}</view>
				<view class="t2">{{workTime}}小时</view>
				<view class="t1"  @click="choseType('pm')">{{endTime}}</view>
			</view>
			<view class="workTime">
				<view :class="timeType=='am'?'t1 typecolor' :'t1'" @click="timeType='am';"
				style="border: none;" >00:00-11:59</view>
				<view class="t2"> </view>
				<view :class="timeType=='pm'?'t1 typecolor' :'t1'" @click="timeType='pm'"
				style="border: none;" >12:00-23:59</view>
			</view>
			<view class="timebox">
				 
				<view class="time" v-if="timeType=='am'">
					<view v-for="(item,index) in amlist" :key="index" :class="startTime==item ? 'activetime' : ''" 
					@click="changetime(item,'am')">
						{{item}}
					</view>
				</view>
				 
				<view class="time" v-if="timeType=='pm'">
					<view v-for="(it,i) in pmlist" :key="'pm'+i" :class="endTime==it ? 'activetime' : ''" 
					@click="changetime(it,'pm')">
						{{it}}
					</view>
				</view>
			</view> 
			
			<view class="woodsbtn btn" @click="handleTime">
				确定
			</view>
			
			
		</view>
		
	</u-popup>
</template>

<script>
	import calculateTimeDifference from "@/utils/calculateTimeDifference.js"
	export default {
		name:"choseTime",
		data() {
			return {
				show:true,
				startTime:"",
				endTime:"",
				amlist:["7:00","7:30","8:00","8:30"],
				pmlist:["12:00","13:30","14:00","19:30"],
				workTime:"0",
				timeType:"am"
			};
		},
		methods:{
			handleTime(){
				if(this.workTime==0){
					uni.showToast({
						title:'请选择服务时间',
						icon:'none'
					})
					return
				}
				this.$emit('handleTime',{
					startTime:this.startTime,
					endTime:this.endTime,
					workTime:this.workTime
				})
				this.show = false
			},
			open() {
				// console.log('open');
			},
			close() {
				this.show = false
			},
			choseType(type){
				this.timeType=type
			},
			changetime(item,type){
				if (type=='am') {
					this.startTime=item
					this.timeType='pm'
				}else if (type=='pm') {
					this.endTime=item
				} 
				if(this.startTime && this.endTime){
					this.workTime=calculateTimeDifference(this.startTime,this.endTime)
				} 
				 
			},
		}
		
	}
</script>

<style scoped lang="scss">
.title{
	text-align: center;
	line-height: 50rpx;
	font-weight: bold;
	padding: 30rpx;
	
}
.workTime{
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20rpx;
	.t1{
		border-bottom: 1px solid #EEEEEE;
		width: 220rpx;
		margin: 0 30rpx;
		height:60rpx;
		text-align: center;
	}
	.t2{
		height: 60rpx;
		width: 160rpx;
		text-align: center;
		font-size: 28rpx;
		color: #999999;
	}
	.typecolor{
		font-weight: bold;
		font-size: 32rpx;
		color: #277EEF;
	}
}
.timebox{
	padding: 10rpx 0;
	.timetitile{
		font-size: 36rpx;
		font-weight: bold;
		padding: 0 30rpx;
	}
	.time{
		display: flex;
		align-items: center;
		flex-wrap: wrap;
		margin-top: 20rpx;
		margin-bottom: 60rpx;
		>view{
			// width: 120rpx;
			padding:20rpx 35rpx;
			margin: 15rpx;
			// height: 60rpx;
			 
			background-color: #F2F2F2;
			border-radius: 8rpx
		}
		.activetime{
			border: 1px solid #277EEF;
			color: #277EEF;
		}
	}
}
.chosetime{
	position: fixed;
	left: 5%;
	bottom: 80rpx;
	width: 90%;
	background: linear-gradient(#FF7134,#FF3A3E);
	border-radius:20rpx;
	padding: 20rpx;
	display: flex;
	align-items: center;
	justify-content: space-between;
	.tleft{
		color: #fff;
		text{
			font-size: 36rpx;
			color: #fff;
		}
	}
	.tright{
		width: 200rpx;
		height:80rpx;
		background: #ffc368;
		border-radius: 12rpx;
		text-align: center;
		line-height: 80rpx;
		color: #594423;
	}
}
.btn{
	width: 90%;
	margin-bottom: 40rpx;
}

</style>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.

组件结构与实现

模板(Template)

模板部分使用Vue的模板语法定义了组件的HTML结构。包括标题、时间选择区域、时间列表、确认按钮等元素。通过绑定不同的数据属性和事件监听器,实现了动态渲染和交互逻辑。

脚本(Script)

脚本部分包含组件的逻辑代码,主要涉及以下几个方面:

  1. 数据绑定:定义了组件所需的数据属性,如show控制弹窗显示状态,startTimeendTime分别存储所选的开始和结束时间,以及时间列表和工作时长等。
  2. 方法定义
  • handleTime:用户点击确定按钮时触发,检查是否选择了时间,然后通过事件向父组件传递选择结果。
  • open 和 close:处理弹窗的打开和关闭逻辑。
  • choseType:根据用户点击上午或下午,改变当前时间类型。
  • changetime:根据用户选择的时间更新开始或结束时间,并计算工作时长。
  1. 计算工作时长:引入了一个外部工具函数calculateTimeDifference来计算两个时间点之间的时差。

样式(Style)

使用SCSS编写组件样式,确保组件在不同设备上都能呈现良好的视觉效果。包括标题样式、时间选择区域布局、时间按钮的激活状态等。

关键技术点

  • 条件渲染:利用Vue的v-ifv-for指令,根据timeType的值动态渲染上午或下午的时间列表。
  • 事件处理:通过@click绑定事件监听器,实现时间选择和确定按钮的功能。
  • 外部工具函数:引入外部JS文件计算时间差,保持业务逻辑的清晰分离。

该函数用于计算两个时间字符串之间的时间差。它首先将时间字符串转换为分钟数,然后计算时间差(以分钟为单位),最后将时间差转换回"HH:mm"格式并返回。

calculateTimeDifference.js

function calculateTimeDifference(startTime, endTime) {
    /**
     * 计算两个时间字符串之间的时间差。
     *
     * 参数:
     * - startTime (string): 开始时间,格式为 "HH:mm"。
     * - endTime (string): 结束时间,格式为 "HH:mm"。
     *
     * 返回:
     * - string: 时间差,格式为 "HH:mm"。
     *
     * 示例:
     * - 输入 "8:30", "9:45" 返回 "1:15"
     */
	
    // 将时间字符串转换为分钟数
    function timeToMinutes(timeStr) {
        const [hours, minutes] = timeStr.split(':').map(Number);
        return hours * 60 + minutes;
    }

    // 计算时间差(以分钟为单位)
    const startMinutes = timeToMinutes(startTime);
    const endMinutes = timeToMinutes(endTime);
    const diffMinutes = endMinutes - startMinutes;

    // 将时间差转换回"HH:mm"格式
    function minutesToTime(minutes) {
        const hours = Math.floor(minutes / 60);
        const mins = minutes % 60;
        return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;
    }

    return minutesToTime(diffMinutes);
}
export default calculateTimeDifference;
// 使用示例
// const startTime = "8:30";
// const endTime = "9:45";
// const totalTimeDiff = calculateTimeDifference(startTime, endTime);
// console.log(totalTimeDiff); // 输出 "1:15"
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.

结语

通过上述步骤,我们成功创建了一个灵活且易用的时间段选择组件,它不仅提升了用户体验,也展示了Vue.js在构建复杂UI组件方面的强大能力。此组件可以广泛应用于需要精确时间选择的场景,如预约服务、会议安排等。希望本文能为开发者在实现类似功能时提供一定的参考和启发。