活动日历组件,从周一开始
功能:
1、左右按钮为【上一周】【下一周】。日期显示一到日(对应为周一到周日)
2、默认选中当前日期;
3、 点击对应月份的时间,则该月份亮起,顶部时间显示对应月份。
4、 如一周内出现两个月份,则当前选择的月份正常显示,未选中页面则置灰。
关键代码:
<template>
<div class="weekly-calendar">
<h2>{{ showMonth }}</h2>
<div class="controls">
<button class="prev-btn" @click="prevWeek">Prev</button>
<button class="next-btn" @click="nextWeek">Next</button>
</div>
<div class="days">
<div class="day-labels">
<div class="day-label">一</div>
<div class="day-label">二</div>
<div class="day-label">三</div>
<div class="day-label">四</div>
<div class="day-label">五</div>
<div class="day-label">六</div>
<div class="day-label">日</div>
</div>
<div class="day-cells">
<div class="day-cell" v-for="(day, index) in days" :key="index"
:class="{ today: (isToday(day) && !checkIndex) || checkIndex == index, 'not-in-month': !isInMonth(day) }">
<div class="day-number" @click="clickDays(index, day)">{{ isToday(day) ? '今天' : format(day, "dd") }}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { format } from "date-fns";
export default {
data() {
return {
currentWeek: {
start: null,
end: null
},
checkIndex: null,// 当前选中index
showMonth: null // 当前显示月份
};
},
computed: {
days() {
const days = [];
const weekStart = this.currentWeek.start;
const weekEnd = this.currentWeek.end;
const diff = (weekEnd.getTime() - weekStart.getTime()) / (24 * 60 * 60 * 1000);
for (let i = 0; i <= diff; i++) {
const day = new Date(weekStart.getTime() + i * 24 * 60 * 60 * 1000);
days.push(day);
}
return days;
}
},
methods: {
format,
clickDays(index, day) {
this.checkIndex = index
this.seShowMonth(day)
},
prevWeek() {
this.checkDay = null
const firstDayOfWeek = 1;
const weekStart = this.currentWeek.start;
const prevWeekStart = new Date(weekStart.getTime() - 7 * 24 * 60 * 60 * 1000);
this.currentWeek.start = new Date(
prevWeekStart.getTime() - (prevWeekStart.getDay() - firstDayOfWeek) * 24 * 60 * 60 * 1000
);
this.currentWeek.end = new Date(
this.currentWeek.start.getTime() + 6 * 24 * 60 * 60 * 1000
);
this.checkIndex = 3
const day = new Date(this.currentWeek.end.getTime() - 3 * 24 * 60 * 60 * 1000);
this.seShowMonth(day)
},
nextWeek() {
this.checkDay = null
const firstDayOfWeek = 0;
const weekEnd = this.currentWeek.end;
const nextWeekEnd = new Date(weekEnd.getTime() + 7 * 24 * 60 * 60 * 1000);
this.currentWeek.end = new Date(
nextWeekEnd.getTime() + (firstDayOfWeek - nextWeekEnd.getDay()) * 24 * 60 * 60 * 1000
);
this.currentWeek.start = new Date(
this.currentWeek.end.getTime() - 6 * 24 * 60 * 60 * 1000
);
this.checkIndex = 3
const day = new Date(this.currentWeek.start.getTime() + 3 * 24 * 60 * 60 * 1000);
this.seShowMonth(day)
},
isToday(date) {
const today = new Date();
return date.toDateString() === today.toDateString();
},
isInMonth(date) {
return format(date, "yyyy/MM") == this.showMonth
},
seShowMonth(day) {
this.showMonth = format(day, "yyyy/MM")
},
setToday() {
const firstDayOfWeek = 1;
const today = new Date();
const currentWeekStart = new Date(
today.getTime() - (today.getDay() - firstDayOfWeek) * 24 * 60 * 60 * 1000
);
this.currentWeek.start = currentWeekStart;
this.currentWeek.end = new Date(
currentWeekStart.getTime() + 6 * 24 * 60 * 60 * 1000
);
this.seShowMonth(this.currentWeek.start)
}
},
created() {
this.setToday()
}
};
</script>
<style scoped>
.weekly-calendar {
max-width: 500px;
margin: 0 auto;
font-family: Arial, sans-serif;
}
.weekly-calendar h2 {
text-align: center;
}
.weekly-calendar .controls {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.weekly-calendar .day-labels {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.weekly-calendar .day-label {
flex: 1;
text-align: center;
font-size: 16px;
font-weight: bold;
}
.weekly-calendar .day-cells {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.weekly-calendar .day-cell {
flex: 1;
border: 1px solid #ccc;
padding: 10px;
text-align: center;
}
.weekly-calendar .today {
background-color: #f9f9f9;
}
.weekly-calendar .not-in-month {
color: #ccc;
}
</style>