vue 平铺日历选择组件封装(支持选择时间点或时间段)

项目中遇到进行日期选择的需求,直接平铺在页面上,如下图所示
在这里插入图片描述

<template>
	<div class="date-calender">
		<div class="header-title">
			<i @click="preYear" class="el-icon-d-arrow-left"></i>
			<i @click="preMon" class="el-icon-arrow-left"></i>
			<a class="data-now-a">{{currentYear}}年{{currentMonth+1}}月</a>
			<i @click="nextMon" class="el-icon-arrow-right"></i>
			<i @click="nextYear" class="el-icon-d-arrow-right"></i>

		</div>
		<div class="flex-week">
			<a class="a-week" v-for="(item,index1) in listXIngqi" :key="index1">{{ item }}</a>
		</div>
		<ul class="date">
			<!-- 标记当前时间 -->
			<!-- <li v-for="(item, index) in list" :key="index" @click="handerSelect(item)" class="riqili"
				:class="[( Number(item.y+''+item.m+''+item.d)  >= Number(starttime)  && Number(endtime)  >= Number(item.y+''+item.m+''+item.d)  || 
            item.y+''+item.m+''+item.d == starttime||  item.y+''+item.m+''+item.d == endtime ) ? 'activeSelect' : '',(item.y === year && item.m === month && item.d === day)?'current-day-cricle':'',item.isSign?'sign-select':'']">
				<div class="day" :class="{'text-color': item.cur}">
					{{item.d}}
					<a :class="item.y+''+item.m+''+item.d"></a>
				</div>
			</li> -->
			<!-- 不标记当前时间 -->
			<li v-for="(item, index) in list" :key="index" @click="handerSelect(item)" class="riqili"
				:class="[( Number(item.y+''+item.m+''+item.d)  >= Number(starttime)  && Number(endtime)  >= Number(item.y+''+item.m+''+item.d)  || 
            item.y+''+item.m+''+item.d == starttime||  item.y+''+item.m+''+item.d == endtime ) ? 'current-day-cricle' : '',item.isSign?'sign-select':'',(item.y === year && item.m === month && item.d === day)?'sign-quick' : '']">
				<div class="day" :class="{'text-color': item.cur}">
					{{item.d}}
					<a :class="item.y+''+item.m+''+item.d"></a>
				</div>
			</li>
			<li class="bg-month">{{currentMonth+1}}</li>
			<li @click="getCurrentDate" class="quick-day-btn">今天</li>
		</ul>
	</div>
</template>
<script>
export default {
	data() {
		return {
			// year: new Date().getFullYear(), // 今日年份
			// month: new Date().getMonth() + 1, // 今日月份
			// day: new Date().getDate() > 9 ? new Date().getDate() : `0${new Date().getDate()}`, // 今日日份
			year: '', // 今日年份
			month: '', // 今日月份
			day: '', // 今日日份
			isQuick: false, //是否快捷今日
			currentYear: '', // 当前显示年份
			currentMonth: '', // 当前显示月份 0-11,显示时加一
			currentDay: '', // 当前显示日份
			monthDays: [], // 1-12月的天数
			list: [],
			listXIngqi: ['日', '一', '二', '三', '四', '五', '六'],
			// listXIngqi: ['一', '二', '三', '四', '五', '六', '日'],
			selectCompare: [],
			clickcount: 0, //点击次数
			starttime: '', //点击的开始的日期
			endtime: '', //点击的结束时间 数字
			params_starttime: '', //抛出去的参数
			params_endtime: '' //抛出去的参数
		};
	},
	props: {
		isSingleChoice: {
			type: Boolean,
			default: true
		},
		signArr: {
			type: Array,
			default: () => []
		}
	},
	mounted() {
		this.showCalender();
	},
	methods: {
		// 点击的日期
		handerSelect(mess) {
			if (mess.cur) {
				// 清除快捷标记
				if (!mess.isToQuick) {
					this.year = ''; // 今日年份
					this.month = ''; // 今日月份
					this.day = '';
				}
				// 点击的是当前月
				this.clickcount++;
				if (this.isSingleChoice) {
					this.starttime = mess.y + '' + mess.m + '' + mess.d;
					let activeDate = this.$Tool.formate(`${mess.y}/${mess.m}/${mess.d}`, 'yyyy-MM-dd');
					this.$emit('change', activeDate);
				} else {
					// 选择时间段
					if (this.clickcount % 2 == 1) {
						// 开始时间
						this.starttime = mess.y + '' + mess.m + '' + mess.d;
						this.endtime = '';
						this.params_starttime =
							mess.y +
							'-' +
							(mess.m > 9 ? mess.m : '0' + mess.m) +
							'-' +
							(mess.d > 9 ? mess.d : '0' + mess.d);
						this.params_endtime = '';
					} else {
						// 结束时间
						this.endtime = mess.y + '' + mess.m + '' + mess.d;
						this.params_endtime =
							mess.y +
							'-' +
							(mess.m > 9 ? mess.m : '0' + mess.m) +
							'-' +
							(mess.d > 9 ? mess.d : '0' + mess.d);
						if (Number(this.starttime) > Number(this.endtime)) {
							this.endtime = Number(this.starttime);
							this.params_endtime = this.params_starttime;
							this.starttime = Number(mess.y + '' + mess.m + '' + mess.d);
							this.params_starttime =
								mess.y +
								'-' +
								(mess.m > 9 ? mess.m : '0' + mess.m) +
								'-' +
								(mess.d > 9 ? mess.d : '0' + mess.d);
						}
					}
					this.$emit('change', [this.params_starttime, this.params_endtime]);
				}
			} else {
				// if(mess.d>20){
				//     this.nextMon();
				// }else{
				//     this.preMon();
				// }
			}
		},

		isLeap(year) {
			// 判断是不是闰年
			return year % 100 === 0 ? (year % 400 === 0 ? 1 : 0) : year % 4 === 0 ? 1 : 0;
		},

		showCalender(type) {
			console.log(type);
			this.list = [];
			this.newDate = new Date();
			if (!type) this.currentYear = this.newDate.getFullYear();
			if (!type) this.currentMonth = this.newDate.getMonth();
			this.monthDays = [
				31,
				28 + this.isLeap(this.currentYear),
				31,
				30,
				31,
				30,
				31,
				31,
				30,
				31,
				30,
				31
			];
			this.currentDay = this.newDate.getDate();
			this.firstDay = new Date(`${this.currentYear}-${this.currentMonth + 1}-1`);
			this.firstnow = this.firstDay.getDay(); // 当月第一日是星期几 1-7
			// if (this.firstnow === 0) this.firstnow = 7;   //一周从周一开始的写法
			// 从周一开始判断this.firstnow > 1  减去等于的情况
			if (this.firstnow >= 1) {
				// 前一个月份
				let monIndex = this.currentMonth;
				let year;
				if (monIndex === 0) {
					year--;
					monIndex = 11;
				} else {
					monIndex--;
				}
				//一周从周一开始的写法
				// for (let i = 0; i < this.firstnow - 1; i++) {
				// 	this.list.unshift({
				// 		y: year,
				// 		m: monIndex + 1,
				// 		d: this.monthDays[monIndex] - i
				// 	});
				// }
				for (let i = 0; i < this.firstnow; i++) {
					this.list.unshift({
						y: year,
						m: monIndex + 1,
						d: this.monthDays[monIndex] - i
					});
				}
			}
			for (let i = 0; i < this.monthDays[this.currentMonth]; i++) {
				// 标记当天时间
				let dateF = `${this.currentYear}/${this.currentMonth + 1>9?this.currentMonth + 1:`0${this.currentMonth + 1}`}/${i + 1 > 9 ? i + 1 : `0${i + 1}`}`;
				let dateSignF = this.signArr.filter((df) => {
					let dfFormate = this.$Tool.formate(df, 'yyyy/MM/dd');
					return dfFormate == dateF;
				});
				// 当前月份
				this.list.push({
					y: this.currentYear,
					m: this.currentMonth + 1,
					d: i + 1 > 9 ? i + 1 : `0${i + 1}`,
					cur: true,
					isSign: dateSignF.length > 0 ? true : false
				});
			}
			//一周从周一开始的写法
			// const num = (this.monthDays[this.currentMonth] + this.firstnow - 1) % 7;
			const num = (this.monthDays[this.currentMonth] + this.firstnow) % 7;
			// 从周一开始判断num > 0  减去等于的情况
			if (num >= 0) {
				// 下个月份
				let monIndex2 = this.currentMonth;
				let year2;
				if (monIndex2 === 11) {
					year2++;
					monIndex2 = 0;
				} else {
					monIndex2++;
				}
				if (num > 0) {
					for (let i = 0; i < 7 - num; i++) {
						this.list.push({
							y: year2,
							m: monIndex2 + 1,
							d: i + 1
						});
					}
				}
			}
		},
		clearData() {
			this.clickcount = 0;
			this.starttime = '';
			this.endtime = '';
			this.params_starttime = '';
			this.params_endtime = '';
		},
		// 上个月
		preMon() {
			this.clearData();
			if (this.currentMonth === 0) {
				this.currentYear--;
				this.currentMonth = 11;
			} else {
				this.currentMonth--;
			}
			this.showCalender('pre');
		},
		// 下个月
		nextMon() {
			this.clearData();
			if (this.currentMonth === 11) {
				this.currentYear++;
				this.currentMonth = 0;
			} else {
				this.currentMonth++;
			}
			this.showCalender('next');
		},
		// 上一年
		preYear() {
			this.clearData();
			this.currentYear--;
			this.showCalender('pre');
		},
		// 下一年
		nextYear() {
			this.clearData();
			this.currentYear++;
			this.showCalender('next');
		},
		// 今日
		getCurrentDate() {
			let _date = {
				cur: true,
				d: new Date().getDate(),
				isSign: true,
				m: new Date().getMonth() + 1,
				y: new Date().getFullYear(),
				isToQuick: true
			};
			this.year = new Date().getFullYear(); // 今日年份
			this.month = new Date().getMonth() + 1; // 今日月份
			this.day = new Date().getDate() > 9 ? new Date().getDate() : `0${new Date().getDate()}`; // 今日日份
			this.handerSelect(_date);
		}
	}
};
</script>
<style lang="scss" scoped>
@import '@/assets/css/travel-mixin.scss';
.date-calender {
	display: flex;
	justify-content: center;
	flex-direction: column;
	align-items: center;
	.header-title {
		width: 220px;
		height: 40px;
		opacity: 1;
		// background: #f8f8f7;
		display: flex;
		justify-content: center;
		align-items: center;
		justify-content: space-between;
		padding: 0 10px;
		margin-top: 40px;
		margin-bottom: 17px;
		border-bottom: 1px solid $brdededed;
		i {
			font-size: 12px;
			color: rgba(0, 0, 0, 0.45);
			cursor: pointer;
		}
		.data-now-a {
			font-size: 15px;
			font-family: Helvetica, Helvetica-Regular;
			font-weight: 400;
			color: rgba(0, 0, 0, 0.85);
			width: 100 px;
			text-align: center;
			font-size: 14px;
			font-weight: 500;
		}
	}

	.flex-week {
		display: flex;
		justify-content: space-between;
		width: 210px;
		.a-week {
			font-size: 0;
			font-size: 14px;
			font-family: Helvetica, Helvetica-Regular;
			font-weight: 400;
			text-align: center;
			color: #253f50;
			display: inline-block;
			width: 30px;
			height: 30px;
		}
	}

	.date {
		position: relative;
		display: flex;
		justify-content: flex-start;
		align-content: flex-start;
		flex-wrap: wrap;
		align-items: center;
		width: 210px;
		height: 180px;
		.riqili {
			// height: 28px;
			// width: 28px;
			// border: 1px solid transparent;
			width: 30px;
			height: 30px;
			display: flex;
			// 末尾或者上月天数颜色
			justify-content: center;
			align-items: center;
			color: $cdisabled;
			font-size: 14px;
			position: relative;
			z-index: 0;
			//当前月的正常颜色
			.text-color {
				// font-size: 0;
				font-size: 14px;
				font-family: Helvetica, Helvetica-Regular;
				font-weight: 400;
				text-align: center;
				color: #595959;
			}
		}
		.riqili:nth-child(7n) {
			margin-right: 0px;
		}
	}
	.activeSelect {
		width: 28px;
		height: 28px;
		opacity: 1;
		border: 1px solid $comain !important;
		border-radius: 50%;
		.day {
			color: $comain !important;
		}
	}
	// 标识日期
	.sign-select {
		width: 28px;
		height: 28px;
		opacity: 1;
		background: $cdate-status;
		border: 1px solid $cdate-status !important;
		border-radius: 50%;
		.day {
			color: $c6 !important;
		}
	}
	// 背景月份
	.bg-month {
		width: 120px;
		position: absolute;
		top: 0px;
		left: 50%;
		margin-left: -60px;
		font-size: 100px;
		color: $cbgmain;
		z-index: -1;
		cursor: pointer;
		text-align: center;
	}
	// 当天快捷键
	.quick-day-btn {
		position: absolute;
		bottom: -50px;
		width: 100%;
		height: 40px;
		line-height: 40px;
		margin-top: 30px;
		text-align: center;
		border: 1px solid $comain;
		border-radius: 4px;
		background: $cbgmain;
		color: $comain;
		cursor: pointer;
	}
	// 当月当天的标识
	.current-day-cricle,
	.sign-quick {
		display: block;
		width: 30px;
		height: 30px;
		background: $comain;
		border-radius: 50%;
		position: absolute;
		bottom: 0px;
		left: 0px;
		color: $cf;
		z-index: -1;
		.text-color {
			color: $cf !important;
		}
	}
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值