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

在现代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>

组件结构与实现

模板(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"

结语

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