<template>
<div class="calendar">
<div class="header">
<div class="header_left">
<div class="totals">195</div>
<div class="names">累计学习天数</div>
</div>
<div class="header_right">
<div class="arrows" @click="prevMonth"><img src="../../../assets/Layout/home/icon_arrowleft.png" alt="" class="arrow_image"></div>
<span class="same_month">{{ currentYear }}.{{ (currentMonth + 1).toString().padStart(2, '0') }}</span>
<div class="arrows" @click="nextMonth"><img src="../../../assets/Layout/home/icon_arrowright.png" alt="" class="arrow_image"></div>
</div>
</div>
<div class="weekdays">
<div v-for="(day, index) in weekdays" :key="index" class="weekday">{{ day }}</div>
</div>
<div class="days">
<div v-for="(day, index) in days" :key="index" class="day" :class="{ selected: isSelected(day) }" @click="day && toggleDateSelection(day)">
{{ day ? day.getDate() : '' }}
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const currentDate = ref(new Date());
const selectedDates = ref(new Set());
const weekdays = ['一', '二', '三', '四', '五', '六', '日'];
const currentYear = computed(() => currentDate.value.getFullYear());
const currentMonth = computed(() => currentDate.value.getMonth());
const days = computed(() => {
const firstDayOfMonth = new Date(currentYear.value, currentMonth.value, 1);
const lastDayOfMonth = new Date(currentYear.value, currentMonth.value + 1, 0);
const firstDayOfWeek = firstDayOfMonth.getDay();
const daysInMonth = lastDayOfMonth.getDate();
const calendarDays = [];
for (let i = 0; i < firstDayOfWeek; i++) {
calendarDays.push(null); // empty cells for previous month days
}
for (let day = 1; day <= daysInMonth; day++) {
calendarDays.push(new Date(currentYear.value, currentMonth.value, day));
}
return calendarDays;
});
const toggleDateSelection = (day) => {
if (!day) return;
const dateString = day.toISOString().split('T')[0];
if (selectedDates.value.has(dateString)) {
selectedDates.value.delete(dateString);
} else {
selectedDates.value.add(dateString);
}
};
const isSelected = (day) => {
if (!day) return false;
const dateString = day.toISOString().split('T')[0];
return selectedDates.value.has(dateString);
};
const prevMonth = () => {
currentDate.value = new Date(currentYear.value, currentMonth.value - 1, 1);
};
const nextMonth = () => {
currentDate.value = new Date(currentYear.value, currentMonth.value + 1, 1);
};
</script>
<style lang="scss" scoped>
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
.header_left{
.totals{
font-family: Oswald;
font-weight: 700;
font-size: 40px;
background: linear-gradient(to bottom, #E87421 , #FBCE89 );
background-clip: text;
-webkit-background-clip: text;
color: transparent;
}
.names{
font-weight: 400;
font-size: 14px;
color: rgb(0, 0, 0,.7);
}
}
.header_right{
display: flex;
align-items: center;
.arrow_image{
width: 17px;
height: 12px;
}
.same_month{
margin: 0 15px;
font-family: Oswald;
font-weight: 700;
font-size: 16px;
color: rgb(0, 0, 0,.7);
}
.arrows{
cursor: pointer;
}
}
}
.weekdays {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
font-weight: bold;
text-align: center;
margin-bottom: 10px;
font-size: 12px;
}
.days {
display: grid;
grid-template-columns: repeat(7, 1fr);
}
.day {
padding:10px;
box-sizing: border-box;
text-align: center;
cursor: pointer;
font-weight: bold;
font-size: 12px;
margin: 8px;
}
.day.selected {
background: linear-gradient(-90deg, #27C5D4, #69EAF6);
box-shadow: 0px 0px 8px 0px rgba(36,196,211,0.35);
border-radius: 22px;
color: #fff;
}
</style>
手写一个日历,记录签到-vue3
最新推荐文章于 2024-06-15 11:33:02 发布