web/src/components/common/Calendar.vue

171 lines
4.5 KiB
Vue

<script setup lang="ts">
const currentDate = new Date();
const currentMonth = currentDate.getMonth();
const currentYear = currentDate.getFullYear();
// 获取指定月份信息的基础函数
const getFirstDayOfMonth = (year: number, month: number): number => {
return new Date(year, month, 1).getDay();
};
const getDaysInMonth = (year: number, month: number): number => {
return new Date(year, month + 1, 0).getDate();
};
// 优化后的日历生成函数
const generateCalendarData = (
year: number,
month: number
): Array<Array<{ day: number; isCurrentMonth: boolean; isCurrentDay: boolean }>> => {
const weeks: Array<Array<{ day: number; isCurrentMonth: boolean; isCurrentDay: boolean }>> = [];
const daysInMonth = getDaysInMonth(year, month);
const firstDayIndex = getFirstDayOfMonth(year, month);
// 获取当前日期的日部分
const currentDay = currentDate.getDate();
// 计算前后月信息
const prevMonth = month === 0 ? 11 : month - 1;
const nextMonth = month === 11 ? 0 : month + 1;
const prevYear = month === 0 ? year - 1 : year;
const nextYear = month === 11 ? year + 1 : year;
const daysInPrevMonth = getDaysInMonth(prevYear, prevMonth);
const daysInNextMonth = getDaysInMonth(nextYear, nextMonth);
let dayCounter = 1;
let nextMonthDayCounter = 1;
for (let week = 0; week < 5; week++) {
const weekDays = [];
for (let day = 0; day < 7; day++) {
const isFirstWeek = week === 0;
const position = week * 7 + day;
// 当前月日期
if ((isFirstWeek && day >= firstDayIndex) || (!isFirstWeek && dayCounter <= daysInMonth)) {
const isToday = dayCounter === currentDay && month === currentMonth && year === currentYear;
weekDays.push({day: dayCounter, isCurrentMonth: true, isCurrentDay: isToday});
dayCounter++;
}
// 前月日期
else if (isFirstWeek) {
const prevDay = daysInPrevMonth - firstDayIndex + day + 1;
weekDays.push({day: prevDay, isCurrentMonth: false, isCurrentDay: false});
}
// 下月日期
else {
weekDays.push({day: nextMonthDayCounter, isCurrentMonth: false, isCurrentDay: false});
nextMonthDayCounter++;
}
}
weeks.push(weekDays);
}
return weeks;
};
// 使用示例
const calendarData = generateCalendarData(currentYear, currentMonth);
console.log(calendarData);
</script>
<template>
<div class="calendar-wrapper">
<span class="current">{{ currentYear }}{{ currentMonth + 1 }}</span>
<div class="row">
<div class="item">
<span class="tip"></span>
</div>
<div class="item">
<span class="tip"></span>
</div>
<div class="item">
<span class="tip"></span>
</div>
<div class="item">
<span class="tip"></span>
</div>
<div class="item">
<span class="tip"></span>
</div>
<div class="item">
<span class="tip"></span>
</div>
<div class="item">
<span class="tip"></span>
</div>
</div>
<div v-for="item in calendarData" class="row">
<div class="item" v-for="subItem in item">
<span :class="subItem.isCurrentDay ? 'currentDay' : subItem.isCurrentMonth ? '' : 'otherMonth'">
{{ subItem.isCurrentDay ? "今" : subItem.day }}
</span>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.calendar-wrapper {
width: 100%;
height: 100%;
box-sizing: border-box;
padding:0 20px 20px;
background-color: #FFF;
border-radius: 0 0 8px 8px;
display: flex;
flex-direction: column;
.current{
font-weight: 500;
font-size: 18px;
color: #333333;
font-style: normal;
margin-bottom: 8px;
}
.row {
flex: 1;
width: 100%;
background: #F9FAFC ;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 500;
font-size: 14px;
color: #999999;
font-style: normal;
.item {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
span {
margin: auto;
height: 34px;
width: 34px;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
font-size: 16px;
color: #666666;
font-style: normal;
border-radius:17px;
}
.currentDay {
background: #1677FE;
color: #fff;
}
.otherMonth{
color: #999;
}
}
}
}
</style>