| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 | 
							- <template>
 
- 	<view class="page adffc">
 
- 		<div class="week adf">
 
- 			<div class="week-pre adfacjc" v-for="(w, i) in weeks" :class="{ active: i === 0 || i === 6 }" :key="i">{{ w }}</div>
 
- 		</div>
 
- 		<div class="list">
 
- 			<div class="list-item" v-for="(c,i) in calendarsCopy" :key="i">
 
- 				<div class="title">{{c.monthTitle}}</div>
 
- 				<div class="days">
 
- 					<div class="days-pre" 
 
- 					:class="{'active':d.selected&&d.isCurrentMonth,'in':d.inrange&&d.isCurrentMonth}" 
 
- 					v-for="(d,di) in c.days" :key="di">
 
- 						<div class="today" v-if="d.isToday">今天</div>
 
- 						<div class="day adfacjc" :class="{'hui':d.isPast}">{{d.isCurrentMonth?d.day:''}}</div>
 
- 						<div class="se" v-if="d.start&&d.isCurrentMonth">开始</div>
 
- 						<div class="se" v-if="d.end&&d.isCurrentMonth">结束</div>
 
- 					</div>
 
- 				</div>
 
- 			</div>
 
- 		</div>
 
- 	</view>
 
- </template>
 
- <script setup name="ActivityCalendar">
 
- import { ref, onMounted } from 'vue';
 
- const weeks = ['日', '一', '二', '三', '四', '五', '六'];
 
- const calendars = ref([]);
 
- const calendarsCopy = ref([]);
 
- const createCalendar = (months) => {
 
- 	return new Promise((resolve,reject)=>{
 
- 		const calendarList = [];
 
- 		const today = new Date();
 
- 		today.setHours(0, 0, 0, 0); // 标准化日期
 
- 		
 
- 		for (let i = 0; i < months; i++) {
 
- 			// --- 1. 计算目标月份 ---
 
- 			const targetDate = new Date();
 
- 			targetDate.setHours(0, 0, 0, 0);
 
- 			targetDate.setMonth(targetDate.getMonth() + i, 1);
 
- 		
 
- 			const year = targetDate.getFullYear();
 
- 			const month = targetDate.getMonth(); // 0-11
 
- 		
 
- 			const monthData = {
 
- 				monthTitle: `${year}/${String(month + 1).padStart(2, '0')}`,
 
- 				days: []
 
- 			};
 
- 		
 
- 			// --- 2. 计算日历网格的起始和结束日期 ---
 
- 			let startDate;
 
- 			const firstDayOfMonth = new Date(year, month, 1);
 
- 			const lastDayOfMonth = new Date(year, month + 1, 0);
 
- 		
 
- 			// **核心逻辑:根据是否为第一个月,决定网格的起始日期**
 
- 			if (i === 0) {
 
- 				// **第一个月(当前月):** 网格从今天所在周的周日开始
 
- 				startDate = new Date(today);
 
- 				startDate.setDate(today.getDate() - today.getDay());
 
- 			} else {
 
- 				// **后续月份:** 网格从该月第一天所在周的周日开始,保证月份的完整性
 
- 				startDate = new Date(firstDayOfMonth);
 
- 				startDate.setDate(firstDayOfMonth.getDate() - firstDayOfMonth.getDay());
 
- 			}
 
- 		
 
- 			// **网格的结束日期总是该月最后一天所在周的周六**
 
- 			const endDate = new Date(lastDayOfMonth);
 
- 			endDate.setDate(lastDayOfMonth.getDate() + (6 - lastDayOfMonth.getDay()));
 
- 		
 
- 			// --- 3. 循环填充日历网格中的每一天 ---
 
- 			for (let d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) {
 
- 				const currentYear = d.getFullYear();
 
- 				const currentMonth = d.getMonth() + 1;
 
- 				const currentDay = d.getDate();
 
- 		
 
- 				monthData.days.push({
 
- 					day: currentDay,
 
- 					dateStr: `${currentYear}-${String(currentMonth).padStart(2, '0')}-${String(currentDay).padStart(2, '0')}`,
 
- 					isToday: d.getTime() === today.getTime(),
 
- 					// 标识是否属于当前正在生成的月份 (e.g., 在7月数据中,8月1日这项为 false)
 
- 					isCurrentMonth: d.getMonth() === month,
 
- 					// 标识是否为过去日期 (仅在第一个月生效)
 
- 					isPast: i === 0 && d.getTime() < today.getTime()
 
- 				});
 
- 			}
 
- 		
 
- 			calendarList.push(monthData);
 
- 		}
 
- 		resolve(calendarList)
 
- 	})
 
- };
 
- const setStartEndDay = type => {//type 0:全部时间 1:一周内 2:一月内 3:本周末
 
- 	let d = new Date();
 
- 	let s = new Date().Format('yyyy-MM-dd');
 
- 	let e = null;
 
- 	switch(type){
 
- 		case 0:
 
- 			s = e = '';
 
- 			break;
 
- 		case 1:
 
- 			e = new Date(d.setDate(d.getDate(s)+6)).Format('yyyy-MM-dd');
 
- 			break;
 
- 		case 2:
 
- 			e = new Date(d.setDate(d.getDate(s)+30)).Format('yyyy-MM-dd');
 
- 			break;
 
- 		case 3:
 
- 			let sw = new Date(s).getDay();
 
- 			if(sw===0){//当天是周日
 
- 				s = new Date(d.setDate(d.getDate(s)-1)).Format('yyyy-MM-dd');
 
- 				e = new Date(s).Format('yyyy-MM-dd');
 
- 			}else{
 
- 				s = new Date(d.setDate(d.getDate(s)+(6-sw))).Format('yyyy-MM-dd');
 
- 				e = new Date(d.setDate(d.getDate(s)+1)).Format('yyyy-MM-dd');
 
- 			}
 
- 			break;
 
- 	}
 
- 	calendarsCopy.value = JSON.parse(JSON.stringify(calendars.value));
 
- 	if(!s||!e) return
 
- 	calendarsCopy.value.forEach(c=>{
 
- 		c?.days.forEach(d=>{
 
- 			if(d.dateStr===s||d.dateStr===e){
 
- 				d.selected = true;
 
- 				d.start = d.dateStr===s;
 
- 				d.end = d.dateStr===e;
 
- 			}
 
- 			if(Date.parse(new Date(d.dateStr))>Date.parse(new Date(s))&&Date.parse(new Date(d.dateStr))<Date.parse(new Date(e))){
 
- 				d.inrange = true;
 
- 			}
 
- 		})
 
- 	})
 
- }
 
- onMounted(async () => {
 
- 	calendars.value = await createCalendar(2);
 
- 	calendarsCopy.value = JSON.parse(JSON.stringify(calendars.value));
 
- });
 
- defineExpose({
 
- 	setStartEndDay
 
- })
 
- </script>
 
- <style scoped lang="scss">
 
- .page {
 
- 	width: 100%;
 
- 	height: 100%;
 
- 	background: #f7f7f7;
 
- 	.week {
 
- 		width: 100%;
 
- 		height: 81rpx;
 
- 		background: #ffffff;
 
- 		&-pre {
 
- 			width: calc(100% / 7);
 
- 			height: 100%;
 
- 			font-family: PingFangSC, PingFang SC;
 
- 			font-weight: 400;
 
- 			font-size: 24rpx;
 
- 			color: #6b7280;
 
- 			line-height: 33rpx;
 
- 			&.active {
 
- 				font-weight: bold;
 
- 				color: #70cf52;
 
- 			}
 
- 		}
 
- 	}
 
- 	.list {
 
- 		flex: 1;
 
- 		overflow-y: auto;
 
- 		&-item{
 
- 			.title{
 
- 				font-family: PingFang-SC, PingFang-SC;
 
- 				font-weight: bold;
 
- 				font-size: 30rpx;
 
- 				color: #252525;
 
- 				line-height: 30rpx;
 
- 				text-align: center;
 
- 				margin-top: 30rpx;
 
- 			}
 
- 			.days{
 
- 				display: flex;
 
- 				flex-wrap: wrap;
 
- 				margin-top: 40rpx;
 
- 				&-pre{
 
- 					width: calc(100% / 7);
 
- 					height: 120rpx;
 
- 					position: relative;
 
- 					&.active{
 
- 						background: #B7F358;
 
- 					}
 
- 					&.in{
 
- 						background: rgba(183, 243,88, .4);
 
- 					}
 
- 					.day{
 
- 						width: 100%;
 
- 						height: 100%;
 
- 						font-family: PingFang-SC, PingFang-SC;
 
- 						font-weight: bold;
 
- 						font-size: 30rpx;
 
- 						color: #252525;
 
- 						line-height: 42rpx;
 
- 						&.hui{
 
- 							color: #989998;
 
- 						}
 
- 					}
 
- 					.today{
 
- 						width: 100%;
 
- 						font-family: PingFangSC, PingFang SC;
 
- 						font-weight: 400;
 
- 						font-size: 20rpx;
 
- 						color: #989998;
 
- 						line-height: 28rpx;
 
- 						text-align: center;
 
- 						position: absolute;
 
- 						top: 10rpx;
 
- 					}
 
- 					.se{
 
- 						width: 100%;
 
- 						font-family: PingFangSC, PingFang SC;
 
- 						font-weight: bold;
 
- 						font-size: 20rpx;
 
- 						color: #989998;
 
- 						line-height: 28rpx;
 
- 						text-align: center;
 
- 						position: absolute;
 
- 						bottom: 15rpx;
 
- 					}
 
- 				}
 
- 			}
 
- 		}
 
- 	}
 
- }
 
- </style>
 
 
  |