|
|
|
|
@ -1,7 +1,9 @@
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
const currentDate = new Date();
|
|
|
|
|
const currentMonth = currentDate.getMonth();
|
|
|
|
|
const currentYear = currentDate.getFullYear();
|
|
|
|
|
import { ref, computed } from 'vue';
|
|
|
|
|
import {ArrowLeft,ArrowRight} from '@element-plus/icons-vue'
|
|
|
|
|
const currentMonth = ref(new Date().getMonth());
|
|
|
|
|
const currentYear = ref(new Date().getFullYear());
|
|
|
|
|
const selectedDate = ref<{ day: number; isCurrentMonth: boolean } | null>(null);
|
|
|
|
|
|
|
|
|
|
// 获取指定月份信息的基础函数
|
|
|
|
|
const getFirstDayOfMonth = (year: number, month: number): number => {
|
|
|
|
|
@ -21,8 +23,11 @@ const generateCalendarData = (
|
|
|
|
|
const daysInMonth = getDaysInMonth(year, month);
|
|
|
|
|
const firstDayIndex = getFirstDayOfMonth(year, month);
|
|
|
|
|
|
|
|
|
|
// 获取当前日期的日部分
|
|
|
|
|
// 动态获取当前日期
|
|
|
|
|
const currentDate = new Date();
|
|
|
|
|
const currentDay = currentDate.getDate();
|
|
|
|
|
const currentMonthValue = currentDate.getMonth();
|
|
|
|
|
const currentYearValue = currentDate.getFullYear();
|
|
|
|
|
|
|
|
|
|
// 计算前后月信息
|
|
|
|
|
const prevMonth = month === 0 ? 11 : month - 1;
|
|
|
|
|
@ -45,18 +50,18 @@ const generateCalendarData = (
|
|
|
|
|
|
|
|
|
|
// 当前月日期
|
|
|
|
|
if ((isFirstWeek && day >= firstDayIndex) || (!isFirstWeek && dayCounter <= daysInMonth)) {
|
|
|
|
|
const isToday = dayCounter === currentDay && month === currentMonth && year === currentYear;
|
|
|
|
|
weekDays.push({day: dayCounter, isCurrentMonth: true, isCurrentDay: isToday});
|
|
|
|
|
const isToday = dayCounter === currentDay && month === currentMonthValue && year === currentYearValue;
|
|
|
|
|
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});
|
|
|
|
|
weekDays.push({ day: prevDay, isCurrentMonth: false, isCurrentDay: false });
|
|
|
|
|
}
|
|
|
|
|
// 下月日期
|
|
|
|
|
else {
|
|
|
|
|
weekDays.push({day: nextMonthDayCounter, isCurrentMonth: false, isCurrentDay: false});
|
|
|
|
|
weekDays.push({ day: nextMonthDayCounter, isCurrentMonth: false, isCurrentDay: false });
|
|
|
|
|
nextMonthDayCounter++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -68,13 +73,42 @@ const generateCalendarData = (
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 使用示例
|
|
|
|
|
const calendarData = generateCalendarData(currentYear, currentMonth);
|
|
|
|
|
const calendarData = computed(() => generateCalendarData(currentYear.value, currentMonth.value));
|
|
|
|
|
|
|
|
|
|
// 切换月份
|
|
|
|
|
const prevMonth = () => {
|
|
|
|
|
if (currentMonth.value === 0) {
|
|
|
|
|
currentMonth.value = 11;
|
|
|
|
|
currentYear.value -= 1;
|
|
|
|
|
} else {
|
|
|
|
|
currentMonth.value -= 1;
|
|
|
|
|
}
|
|
|
|
|
selectedDate.value = null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const nextMonth = () => {
|
|
|
|
|
if (currentMonth.value === 11) {
|
|
|
|
|
currentMonth.value = 0;
|
|
|
|
|
currentYear.value += 1;
|
|
|
|
|
} else {
|
|
|
|
|
currentMonth.value += 1;
|
|
|
|
|
}
|
|
|
|
|
selectedDate.value = null;
|
|
|
|
|
};
|
|
|
|
|
const emit=defineEmits(['dateClick']);
|
|
|
|
|
const handleDateClick = (day: number) => {
|
|
|
|
|
selectedDate.value = { day, isCurrentMonth:true };
|
|
|
|
|
emit('dateClick',`${currentYear.value}-${currentMonth.value + 1}-${day}` )
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div class="calendar-wrapper">
|
|
|
|
|
<span class="current">{{ currentYear }}年{{ currentMonth + 1 }}月</span>
|
|
|
|
|
<div class="header">
|
|
|
|
|
<span class="btn" @click="prevMonth"><el-icon><ArrowLeft /></el-icon></span>
|
|
|
|
|
<span class="current">{{ currentYear }}年{{ currentMonth + 1 }}月</span>
|
|
|
|
|
<span class="btn" @click="nextMonth"><el-icon><ArrowRight /></el-icon></span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="item">
|
|
|
|
|
<span class="tip">日</span>
|
|
|
|
|
@ -99,18 +133,48 @@ const calendarData = generateCalendarData(currentYear, currentMonth);
|
|
|
|
|
</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 class="item" v-for="subItem in item" @click="handleDateClick(subItem.day)">
|
|
|
|
|
<span :class="[
|
|
|
|
|
subItem.isCurrentDay ? 'currentDay' : '',
|
|
|
|
|
subItem.isCurrentMonth ? '' : 'otherMonth',
|
|
|
|
|
selectedDate && selectedDate.day === subItem.day && selectedDate.isCurrentMonth === subItem.isCurrentMonth ? 'selectedDay' : ''
|
|
|
|
|
]">
|
|
|
|
|
{{ subItem.isCurrentDay ? "今" : subItem.day }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.calendar-wrapper {
|
|
|
|
|
.header {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
.current{
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
color: #333333;
|
|
|
|
|
font-style: normal;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn {
|
|
|
|
|
padding: 5px 10px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #1677FE;
|
|
|
|
|
background-color: #FFF;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
background-color: #1677FE;
|
|
|
|
|
color: #FFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
@ -119,13 +183,7 @@ const calendarData = generateCalendarData(currentYear, currentMonth);
|
|
|
|
|
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%;
|
|
|
|
|
@ -164,7 +222,11 @@ const calendarData = generateCalendarData(currentYear, currentMonth);
|
|
|
|
|
.otherMonth{
|
|
|
|
|
color: #999;
|
|
|
|
|
}
|
|
|
|
|
.selectedDay {
|
|
|
|
|
background: #FFA500;
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</style>
|
|
|
|
|
|