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>
相关推荐
桂月二二32 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
沈梦研2 小时前
【Vscode】Vscode不能执行vue脚本的原因及解决方法
ide·vue.js·vscode
hunter2062062 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb2 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角2 小时前
CSS 颜色
前端·css
轻口味2 小时前
Vue.js 组件之间的通信模式
vue.js
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5763 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579653 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me4 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架