使用APICloud AVM框架封装app日历组件

2022-04-06 13:46:55 浏览数 (1)

​实现的日历效果图

话不多说,上代码!

代码语言:javascript复制
<template>
    <view class="page">
		<safe-area></safe-area>
		<view class="calendar-wrapper">
			<view class="calendar-toolbar">
				<text class="prev" onclick="prevMonth">〈</text>
				<text class="current">{{ currentDateStr }}</text>
				<text class="next" onclick="nextMonth">〉</text>
			</view>
			<view class="calendar-week">
				<text class="week-item" v-for="item of weekList" :key="item">{{ item }}</text>
			</view>
			<view class="calendar-inner">
				<text class="calendar-item" v-for="(item, index) of calendarList" :key="index" :class="this.changestyle(item.disable,item.value)"
				onclick="selDate" :data-val="item.value" :data-status="item.disable" :data-num="item.date">{{ item.date }}</text>
			</view>
		</view>
    </view>
</template>
<script>
	export default {
		name: 'calendar',
		installed(){
			this.setCurrent();
			this.calendarCreator();
		},
		data() {
			return{
				current:{},	
				weekList:['周日','周一','周二','周三','周四','周五','周六'],
				shareDate: new Date(),
				calendarList: [],
				seldate:'点击选择日期',
				selweek:'待定',
			}
		},
		computed: {
			// 显示当前时间
			currentDateStr() {
				let { year, month } = this.current;
				return `${year}年${this.pad(month   1)}月`;
			}
		},
		methods: {
			selDate (e){
				// console.log(JSON.stringify(e.currentTarget.dataset.val));
				let status = e.currentTarget.dataset.status;
				let num = e.currentTarget.dataset.num;
				if(status){
					this.data.seldate = e.currentTarget.dataset.val;
					this.getWeek();
					if(num>7){
						this.prevMonth();
					}
					else{
						this.nextMonth();
					}
				}
				else{
					this.data.seldate = e.currentTarget.dataset.val;
					this.getWeek();
					//重新加载一次日历 改变样式
					this.calendarCreator();
				}
				this.fire('clickDate', this.data.seldate);
			},
			changestyle(status,date){
				if(status){
					return 'calendar-item-disabled';
				}
				else{
					if(date == this.data.seldate){
						return 'calendar-item-checked';
					}
					else{
						return 'calendar-item';
					}
				}
			},
			// 判断当前月有多少天
			getDaysByMonth(year, month) {
				// console.log("本月多少天:" new Date(year, month   1, 0).getDate());
				return new Date(year, month   1, 0).getDate();
			},
			getFirstDayByMonths(year, month) {
				// console.log("本月第一天周几:" new Date(year, month, 1).getDay());
				return new Date(year, month, 1).getDay();
			},
			getLastDayByMonth(year, month) {
				// console.log("本月最后一天周几:" new Date(year, month   1, 0).getDay());
				return new Date(year, month   1, 0).getDay();
			},
			// 对小于 10 的数字,前面补 0
			pad(str) {
				return str < 10 ? `0${str}` : str;
			},
			// 点击上一月
			prevMonth() {
				this.current.month--;
				// 因为 month的变化 会超出 0-11 的范围, 所以需要重新计算
				this.correctCurrent();
				// 生成新日期
				this.calendarCreator();
			},
			// 点击下一月
			nextMonth() {
				this.current.month  ;
				// 因为 month的变化 会超出 0-11 的范围, 所以需要重新计算
				this.correctCurrent();
				// 生成新日期
				this.calendarCreator();
			},
			// 格式化时间,与主逻辑无关
			stringify(year, month, date) {
				let str = [year, this.pad(month   1), this.pad(date)].join('-');
				return str;
			},
			// 设置或初始化 current
			setCurrent(d = new Date()) {
				let year = d.getFullYear();
				let month = d.getMonth();
				let date = d.getDate();
				this.current = {
						year,
						month,
						date
				}
			},
			// 修正 current
			correctCurrent() {
				let { year, month, date } = this.data.current;
 
				let maxDate = this.getDaysByMonth(year, month);
				// 预防其他月跳转到2月,2月最多只有29天,没有30-31
				date = Math.min(maxDate, date);
 
				let instance = new Date(year, month, date);
				this.setCurrent(instance);
			},
			// 生成日期
			calendarCreator() {
				// 一天有多少毫秒
				const oneDayMS = 24 * 60 * 60 * 1000;
 
				let list = [];
				let { year, month } = this.data.current;
 
				// 当前月份第一天是星期几, 0-6
				let firstDay = this.getFirstDayByMonths(year, month);
				// 填充多少天                         
				let prefixDaysLen = firstDay === 0 ? 7 : firstDay;
				// 毫秒数
				let begin = new Date(year, month, 1).getTime() - oneDayMS * prefixDaysLen;
 
				// 当前月份最后一天是星期几, 0-6
				let lastDay = this.getLastDayByMonth(year, month);
				// 填充多少天, 和星期的排放顺序有关
				let suffixDaysLen = lastDay === 0 ? 6 : 6 - lastDay;
				// 毫秒数
				let end = new Date(year, month   1, 0).getTime()   oneDayMS * suffixDaysLen;
 
				while (begin <= end) {
						// 享元模式,避免重复 new Date
						this.data.shareDate.setTime(begin);
						let year = this.data.shareDate.getFullYear();
						let curMonth = this.data.shareDate.getMonth();
						let date = this.data.shareDate.getDate();
						list.push({
								year: year,
								month: curMonth,
								date: date,
								disable: curMonth !== month,
								value: this.stringify(year, curMonth, date)
						});
						begin  = oneDayMS;
				}
				this.data.calendarList = list;			
				// console.log(JSON.stringify(this.data.calendarList));
			},
			//获取选中日期的周几
			getWeek(){
				let index =new Date(this.data.seldate).getDay();
				let weekArr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五','星期六'];
				let week = weekArr[index];
				this.data.selweek = week;
			},
		}
	}
</script>
<style>
    .page {
        height: 100%;
    }
	.calendar-wrapper {
		margin: 10px 10px 0 10px;
		background-color:#3c40c6;
		border-top-left-radius: 10px;
		border-top-right-radius: 10px;
		max-height: 400px;
	}
 
	.calendar-toolbar {
		padding: 10px 10px;
		flex-flow: row nowrap;
		justify-content: space-between;
		align-items: center;		
		border-bottom: 1px solid #fff;
	}
	.prev{
		flex: 1;
		text-align: center;
		color: #fff;
	}
	.current {
		flex: 1;
		text-align: center;
		color: #fff;
	}
	.next{
		flex: 1;
		text-align: center;
		color: #fff;
	}
 
	.calendar-week {
		padding: 5px 10px;
		flex-flow: row nowrap;
		justify-content: space-around;
		align-items: center;
	}
	.week-item { 
		padding: 5px;
		font-weight: bolder;
		font-size: 12px;
		color: #fff;
	}
	.calendar-inner{
		padding: 10px 10px;
		flex-flow: row wrap;
		justify-content: space-around;
		align-items: center;
	}
	.calendar-item {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #fff;
		padding: 5px;
		background-color: #3c40c6;
	}
	.calendar-item-disabled {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #999;
	}
	.calendar-item-checked {
		width:14%;
		font-weight: bolder;
		text-align: center;
		font-size: 15px;
		color: #000000;
		background-color: #ffffff;
		border-radius: 5px;
	}
</style>

其他页面引用

代码语言:javascript复制
<template>
    <view class="page">
		<calendar onclickDate="getSelDate"></calendar>
		<view>
			<text>当前日期是</text>
			<text>{today}</text>
		</view>
    </view>
</template>
<script>
	import '../../components/calendar.stml'  
	export default {
		name: 'test',
		apiready(){
			
		},
		data() {
			return{
				today:''
			}
		},
		methods: {
			getSelDate(e){
				console.log(JSON.stringify(e));
				this.data.today = e.detail;
				api.toast({
					msg:'当前选中日期是:' e.detail
				})
			}
		}
	}
</script>
<style>
    .page {
        height: 100%;
    }
</style>

0 人点赞