小程序时间组件uniapp

这篇博客介绍了如何在uniapp中实现一个自定义的时间选择组件,支持按月和按日两种选择模式,且在按日选择时支持日期区间选择。组件包含了两个按钮(取消和完成)、日期类型切换按钮以及相应的picker-view组件。在按日选择时,用户可以分别选择起始和结束日期,并进行了日期合法性的检查,确保结束日期不早于开始日期。此外,还展示了组件的样式布局和部分事件处理方法。
摘要由CSDN通过智能技术生成

uniapp 时间组件

在此组件中可切换“按月选择”、“按日选择”,按日选择为区间选择

<!-- 日期选择组件 -->
<template>
	<view class="datePicker-box">
		<view class="btn-box">
			<view class="cancel-btn" hover-class="btn-hover" @click="popCancel">取消</view>
			<view class="submit-btn" hover-class="btn-hover" @click="popSubmit">完成</view>
		</view>
		<view class="date-type-box" @click="changeDateType">
			<view class="date-text" v-if="isDayType">按日选择</view>
			<view class="date-text" v-else>按月选择</view>
			<image class="date-img" src="../../static/business/change.png"></image>
		</view>
		<view v-if="isDayType" class="day-box">
			<!-- <view class="field-box">
				<u-field v-model="bgnTime" label-width="0" @click="bgnFocus" :disabled="true" @blur="bgnBlur" class="field"></u-field>
				<view class="range-text">至</view>
				<u-field v-model="endTime" label-width="0" @click="endFocus" :disabled="true" class="field"></u-field>
			</view> -->

			<picker-view v-if="visible" :indicator-style="indicatorStyle" :value="startvalue" @change="startdayChange"
				class="picker-view">
				<picker-view-column>
					<view class="item" v-for="(item, index) in years" :key="index">{{ item }}年</view>
				</picker-view-column>
				<picker-view-column>
					<view class="item" v-for="(item, index) in months" :key="index">{{ item }}月</view>
				</picker-view-column>
				<picker-view-column>
					<view class="item" v-for="(item, index) in days" :key="index">{{ item }}日</view>
				</picker-view-column>
			</picker-view>
			<view class="range-text">至</view>
			<picker-view v-if="visible" :indicator-style="indicatorStyle" :value="endvalue" @change="enddayChange"
				class="picker-view">
				<picker-view-column>
					<view class="item" v-for="(item, index) in years" :key="index">{{ item }}年</view>
				</picker-view-column>
				<picker-view-column>
					<view class="item" v-for="(item, index) in months" :key="index">{{ item }}月</view>
				</picker-view-column>
				<picker-view-column>
					<view class="item" v-for="(item, index) in days" :key="index">{{ item }}日</view>
				</picker-view-column>
			</picker-view>
		</view>
		<view v-else class="month-box">
			<picker-view v-if="visible" :indicator-style="indicatorStyle" :value="value" @change="monChange"
				class="picker-view">
				<picker-view-column>
					<view class="item" v-for="(item, index) in years" :key="index">{{ item }}年</view>
				</picker-view-column>
				<picker-view-column>
					<view class="item" v-for="(item, index) in months" :key="index">{{ item }}月</view>
				</picker-view-column>
			</picker-view>
		</view>
	</view>
</template>
<script>
	export default {
		data: function() {
			const date = new Date();
			const years = [];
			const year = date.getFullYear();
			const months = [];
			const month = date.getMonth() + 1;
			const days = [];
			const day = date.getDate();
			const bigMonth = [1, 3, 5, 7, 8, 10, 12]
			for (let i = 1990; i <= date.getFullYear(); i++) {
				years.push(i);
			}
			for (let i = 1; i <= 12; i++) {
				months.push(i);
			}
			for (let i = 1; i <= 31; i++) {
				days.push(i);
			}
			return {
				isDayType: false,
				bgnTime: '',
				endTime: '',
				title: "picker-view",
				years,
				year,
				months,
				month,
				days,
				day,
				bigMonth,
				startvalue: [9999, month - 1, day - 1],
				endvalue: [9999, month - 1, day - 1],
				visible: true,
				indicatorStyle: `height: 50px;`,
				bgnStamp: '',
				endStamp: ''
			};
		},
		onShow() {},

		watch: {
			isDayType(newName, oldName) {
				if (newName) {
					this.bgnTime = this.getNowFormatDate().currentdate
					this.endTime = this.getNowFormatDate().currentdate
					this.bgnStamp = this.getNowFormatDate().stamp
					this.endStamp = this.getNowFormatDate().stamp
				}
			},
		},
		methods: {
			//按月选择和按日选择tab切换
			changeDateType() {
				this.isDayType = !this.isDayType;
			},
			startdayChange: function(e) {
				const val = e.detail.value;
				this.year = this.years[val[0]];
				this.month = this.months[val[1]];
				this.day = this.days[val[2]];
				//闰年
				    if (this.month === 2) {
				      if (this.year % 4 === 0 && this.year % 100 !== 0) {
				        console.log('闰年')
				        this.setDays(29);
				      } else {
				        console.log('非闰年')
				        this.setDays(28);
				      }
				    } else {
				      //大月
				      if (this.contains(this.bigMonth, this.month)) {
				        this.setDays(31)
				      } else {
				        this.setDays(30)
				      }
				    }
				let ml = this.month.toString().length;
				let dl = this.day.toString().length
				if (ml === 1) {
					this.month = '0' + this.month
				}
				if (dl === 1) {
					this.day = '0' + this.day
				}
				this.bgnTime = this.year + "年" + this.month + "月" + this.day + "日";
				this.bgnStamp = this.year + "-" + this.month + "-" + this.day;
			},
			enddayChange: function(e) {
				const val = e.detail.value;
				this.year = this.years[val[0]];
				this.month = this.months[val[1]];
				this.day = this.days[val[2]];
				//闰年
				    if (this.month === 2) {
				      if (this.year % 4 === 0 && this.year % 100 !== 0) {
				        console.log('闰年')
				        this.setDays(29);
				      } else {
				        console.log('非闰年')
				        this.setDays(28);
				      }
				    } else {
				      //大月
				      if (this.contains(this.bigMonth, this.month)) {
				        this.setDays(31)
				      } else {
				        this.setDays(30)
				      }
				    }
				let ml = this.month.toString().length;
				let dl = this.day.toString().length
				if (ml === 1) {
					this.month = '0' + this.month
				}
				if (dl === 1) {
					this.day = '0' + this.day
				}
				this.endTime = this.year + "年" + this.month + "月" + this.day + "日";
				this.endStamp = this.year + "-" + this.month + "-" + this.day;
			},
			//判断元素是否在一个数组
			  contains: function (arr, obj) {
			    var i = arr.length;
			    while (i--) {
			      if (arr[i] === obj) {
			        return true;
			      }
			    }
			    return false;
			  },
			  setDays: function (day) {
			    const temp = [];
			    for (let i = 1; i <= day; i++) {
			      temp.push(i)
			    }
				this.days =  temp
			  },
			monChange: function(e) {
				const val = e.detail.value;
				this.year = this.years[val[0]];
				this.month = this.months[val[1]];
				let ml = this.month.toString().length;
				if (ml === 1) {
					this.month = '0' + this.month
				}
			},
			//弹出框确定
			popSubmit() {
				if (this.isDayType) {
					if (!this.bgnTime) {
						return wx.showToast({
							duration: 2000,
							title: '请选择开始时间',
							icon: 'none',
						})
					}
					if (!this.endTime) {
						return wx.showToast({
							duration: 2000,
							title: '请选择结束时间',
							icon: 'none',
						})
					}
					//结束时间不得早于开始时间
					let bgnStamp = new Date(this.bgnStamp).getTime();
					let endStamp = new Date(this.endStamp).getTime();
					if (endStamp <= bgnStamp) {
						return wx.showToast({
							duration: 2000,
							title: '结束时间不得早于等于开始时间',
							icon: 'none',
						})
					}
					//console.log(this.isDayType,this.bgnTime,this.endTime)
					this.$emit("popSubmit", this.isDayType, this.bgnTime, this.endTime);
					this.popCancel();
				} else {
					this.$emit("popSubmit", this.isDayType, this.month, this.year);
					this.popCancel();
				}
			},
			//弹出框取消
			popCancel() {
				this.$emit("popCancel");
				this.bgnTime = "";
				this.endTime = "";
				this.isDayType = false;
			},
			//时间格式化
			getNowFormatDate() {
				let date = new Date();
				let year = date.getFullYear();
				let month = date.getMonth() + 1;
				let strDate = date.getDate();
				if (month >= 1 && month <= 9) {
					month = "0" + month;
				}
				if (strDate >= 0 && strDate <= 9) {
					strDate = "0" + strDate;
			 }
				let currentdate = year + '年' + month + '月' + strDate + '日';
				let stamp = year + "-" + month + "-" + strDate;
				return {currentdate,stamp};
			}
		},
	};
</script>
<style lang="scss" scoped>
	.picker-view {
		width: 100%;
		height: 266rpx;
		margin-top: 10rpx;
	}

	.item {
		height: 50px;
		line-height: 50rpx;
		align-items: center;
		justify-content: center;
		text-align: center;
	}

	.btn-box {
		width: 100%;
		border: 1rpx solid rgba(0, 0, 0, 0.06);
		height: 87rpx;
		display: flex;
		justify-content: space-between;
		padding: 0 30rpx;
		line-height: 87rpx;
		font-size: 28rpx;
		font-family: PingFang SC, PingFang SC-Regular;
		font-weight: 400;
		color: #111736;

		.btn-hover {
			color: #507df1;
		}

		.submit-btn {
			color: #507df1;
		}
	}

	.day-box {
		display: flex;
		flex-direction: column;
		justify-content: center;
	}

	.range-text {
		font-weight: 700;
		width: 100%;
		background-color: #f8f8f8;
		margin: 5rpx auto;
		text-align: center;
	}

	.field-box {
		display: flex;
		height: 70rpx;
		line-height: 70rpx;
		width: 83%;
		margin: 0 auto;

		.range-text {
			padding: 12rpx 0;
		}
	}

	.field {
		border-bottom: 1px solid #ccc;
		margin-bottom: -10px;
	}

	.date-type-box {
		width: 170rpx;
		height: 49rpx;
		line-height: 49rpx;
		background: #f5f5f5;
		border: 1rpx solid #b8b8b8;
		border-radius: 8rpx;
		display: flex;
		justify-content: space-between;
		padding: 0 16rpx;
		margin: 30rpx 0 0 30rpx;

		.date-text {
			font-size: 24rpx;
			font-family: PingFang SC, PingFang SC-Bold;
			font-weight: 700;
			text-align: left;
			color: #000000;
		}

		.date-img {
			width: 26rpx;
			height: 26rpx;
			margin-top: 12rpx;
		}
	}

	.mon-box {
		height: 430rpx;
		width: 100%;
	}
</style>

效果图
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值