uniapp vue3 封装picker时间选择器 年月日时分秒

1、因为在uniapp中并没有完整的年月日时分秒,所以需要自己写一个组件常用

2、 封装好的组件实际效果

完整代码展示

confirmPickDate 在其他方法是改变后数据

用组件ref调用open(val) 是默认赋值回显

javascript 复制代码
<template>
	<view class="dateTimePicker-container">
		<view class="date-time" v-if="visible">
			<view class="mask" @click.stop="close" />
			<view class="box">
				<view class="header">
					<view class="determine" @click.stop="close">取消</view>
					<view class="determine" @click.stop="confirm" :style="{color: themes.theme1 || '#FF4E09',}">确定
					</view>
				</view>

				<picker-view :indicator-style="indicatorStyle" :value="pickerValue" @change="bindChange"
					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-column>
						<view class="item" v-for="(item,index) in hours" :key="index">{{item}}时</view>
					</picker-view-column>
					<picker-view-column>
						<view class="item" v-for="(item,index) in minutes" :key="index">{{item}}分</view>
					</picker-view-column>
					<picker-view-column>
						<view class="item" v-for="(item,index) in seconds" :key="index">{{item}}秒</view>
					</picker-view-column>
				</picker-view>
			</view>
		</view>

	</view>
</template>

<script setup>
	import {
		ref,
		watch,
		getCurrentInstance,
		defineProps,
		onMounted
	} from 'vue'
	const emits = defineEmits(["confirmPickDate"]);


	let years = ref([]),
		year = ref(null),
		months = ref([]),
		month = ref(null),
		days = ref([]),
		day = ref(null),
		hours = ref([]),
		hour = ref(null),
		minutes = ref([]),
		minute = ref(null),
		second = ref(null),
		seconds = ref([]),
		pickerValue = ref([]),
		indicatorStyle = ref('height: 50px;'),
		timeValue = ref(''),
		visible = ref(false)


	// const {
	// 	proxy
	// } = getCurrentInstance();

	let props = defineProps({
		themes: {
			type: Object,
			default () {
				return {}
			}
		},
		interviewTime: {
			type: String,
			default: ''
		}
	})

	onMounted(() => {
		init()

	})


	const init = (interviewTime) => {
		const date = interviewTime ? new Date(interviewTime) : new Date();
		const Years = []
		const Year = date.getFullYear()
		const Months = []
		const Month = date.getMonth() + 1
		const Days = []
		const Day = date.getDate()
		const Hours = []
		const Hour = date.getHours()
		const Minutes = []
		const Minute = date.getMinutes()
		const Seconds = []
		const Second = date.getSeconds()

		let isDay = 30;
		if (Month == 2) {
			if ((Year % 4 == 0 && Year % 100 != 0) || (Year % 400 == 0)) {
				console.log('闰年')
				isDay = 29;
			} else {
				isDay = 28;
				console.log('平年')
			}
		} else if ([1, 3, 5, 7, 8, 10, 12].includes(Month)) {
			isDay = 31;
		} else {
			isDay = 30;
		}

		for (let i = date.getFullYear() - 100; i <= date.getFullYear() + 100; i++) {
			Years.push(i)
		}
		for (let i = 1; i <= 12; i++) {
			Months.push(i)
		}
		for (let i = 1; i <= isDay; i++) {
			Days.push(i)
		}
		for (let i = 0; i <= 23; i++) {
			if (i < 10) {
				Hours.push('0' + i)
			} else {
				Hours.push(i)
			}
		}
		for (let i = 0; i <= 59; i++) {
			if (i < 10) {
				Minutes.push('0' + i)
				Seconds.push('0' + i)
			} else {
				Minutes.push(i)
				Seconds.push(i)
			}
		}

		years.value = Years
		year.value = Year
		months.value = Months
		month.value = Month
		days.value = Days
		day.value = Day
		hours.value = Hours
		hour.value = Hour
		minutes.value = Minutes
		minute.value = Minute
		seconds.value = Seconds
		second.value = Second
		pickerValue.value = [Years.indexOf(Year), Month - 1, Day - 1, Hour, Minute, second]
		return pickerValue.value
	}


	const bindChange = (e) => {
		const val = e.detail.value

		let Year = years.value[val[0]]
		let isDay = 30,
			Days = [];
		if (val[1] + 1 == 2) {
			if ((val[0] % 4 == 0 && Year % 100 != 0) || (Year % 400 == 0)) {
				console.log('闰年')
				isDay = 29;
			} else {
				isDay = 28;
				console.log('平年')
			}
		} else if ([1, 3, 5, 7, 8, 10, 12].includes(val[1] + 1)) {
			isDay = 31;
		} else {
			isDay = 30;
		}

		for (let i = 1; i <= isDay; i++) {
			Days.push(i)
		}
		days.value = Days;
		year.value = years.value[val[0]]
		month.value = months.value[val[1]]
		day.value = days.value[val[2]]
		hour.value = hours.value[val[3]]
		minute.value = minutes.value[val[4]]
		second.value = seconds.value[val[5]]

	}

	const padZeroStr = (originStr) => {
		if (+originStr < 10) {
			return String(originStr).padStart(2, '0')
		}
		return originStr + ''

	}
	const close = () => {
		visible.value = false
	}

	//val时回显
	const open = (val) => {
		visible.value = true
		if (val !== "" && val) {
			// 调用convertDateString处理val,获取年份和其他值
			const [yearVal, monthVal, dayVal, hourVal, minuteVal, secondVal] = convertDateString(val);
			// 更新year.value和pickerValue
			year.value = yearVal;
			pickerValue.value = [years.value.indexOf(yearVal), monthVal, dayVal, hourVal, minuteVal, secondVal];
			console.log(pickerValue.value, "pickerValue.value");
		}
	}

	const confirm = () => {
		let monthStr = padZeroStr(month.value)
		let dayStr = padZeroStr(day.value)
		let hourStr = padZeroStr(hour.value)
		let minuteStr = padZeroStr(minute.value)
		let secondStr = padZeroStr(second.value)
		timeValue.value = `${year.value}-${monthStr}-${dayStr} ${hourStr}:${minuteStr}:${secondStr}`;
		emits('confirmPickDate', timeValue.value);
		close()

	}

	// 将时间分割成数组
	const convertDateString = (dateString) => {
		// 此处简化处理,实际应根据dateString格式进行解析
		let parts = dateString.split(/[- :]/);
		return [
			parseInt(parts[0], 10), // 年份
			parseInt(parts[1], 10) - 1, // 月份减1以适配数组索引
			parseInt(parts[2], 10) - 1, // 日减1以适配数组索引
			parseInt(parts[3], 10), // 小时
			parseInt(parts[4], 10), // 分
			parseInt(parts[5], 10) // 秒
		];
	}

	defineExpose({
		open,
		confirm
	})
</script>

<style lang="scss" scoped>
	.date-time {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100vh;
		z-index: 99999;

		.mask {
			position: absolute;
			top: 0;
			background: rgba(0, 0, 0, 0.5);
			width: 100%;
			height: 100vh;
		}

		.box {
			position: absolute;
			width: 100%;
			bottom: 0;
			background-color: #fff;
			border-radius: 20rpx 20rpx 0 0;
			overflow: hidden;
			height: 600rpx;

			.header {
				height: 88rpx;
				padding: 0 30rpx;
				border-bottom: 1rpx solid #e5e5e5;
				display: flex;
				align-items: center;
				justify-content: space-between;

				.determine {
					color: #333333;
					font-size: 32rpx;
					font-family: PingFang SC, PingFang SC-Regular;
					font-weight: 400;
				}
			}

			.picker-view {
				width: 100%;
				height: 400rpx;
			}

			.item {
				height: 100rpx;
				line-height: 100rpx;
				align-items: center;
				justify-content: center;
				text-align: center;
				font-size: 32rpx;
				font-family: PingFang SC-Regular, PingFang SC;
				font-weight: 400;
				color: #333333;
			}
		}
	}
</style>
相关推荐
迷雾漫步者1 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-1 小时前
验证码机制
前端·后端
燃先生._.2 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖3 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235243 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240254 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar4 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人5 小时前
前端知识补充—CSS
前端·css
GISer_Jing5 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试