1、组件代码 gy-calendar-self.vue
<template>
<view class="calendar">
<view class="selsct-date">
请选择预约日期
</view>
<!-- 日历头部,显示星期 -->
<view class="weekdays">
<view v-for="day in weekDays" :key="day" class="weekday">{{ day }}</view>
</view>
<!-- 日历主体 -->
<view class="calendar-body">
<view v-for="(week, weekIndex) in calendarData" :key="weekIndex" class="week">
<view
v-for="(day, dayIndex) in week"
:key="dayIndex"
@click="selectDate(day)"
:class="{'has-schedule': day.schState !== 0 }"
class="day"
:style="{ width: cellWidth + 'rpx' }"
>
<view class="day-label">{{ day.dateLabel }}</view>
<view v-if="day.day"
class="day-status-has"
:class="[day.info == '有' ? 'day-status-has' : day.info == '满' ? 'day-status-over' : 'day-status-none']"
>
{{day.info}}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
scheduleData: {
type: Array,
default: () => [],
},
},
data() {
return {
weekDays: ["日", "一", "二", "三", "四", "五", "六"],
calendarData: [],
selectedDate: null,
cellWidth: 100, // 单位为rpx
};
},
created() {
this.generateCalendar();
},
methods: {
generateCalendar() {
const startDate = new Date(this.scheduleData[0].dateWork);
const endDate = new Date(this.scheduleData[this.scheduleData.length - 1].dateWork);
let currentDate = new Date(startDate);
let week = [];
if (currentDate.getDay() !== 0) {
for (let i = 0; i < currentDate.getDay(); i++) {
week.push({});
}
}
while (currentDate <= endDate) {
const dateWork = currentDate.toISOString().split('T')[0];
const schState = this.getScheduleState(dateWork);
const weekDay = currentDate.getDay();
const day = currentDate.getDate();
const dayObject = { date: dateWork, dateLabel: this.formatDateLabel(currentDate), schState, weekDay, day };
week.push(dayObject);
if (currentDate.getDate() === new Date().getDate()) {
// Check if the current date matches the current date
this.selectedDate = dayObject;
}
if (currentDate.getDay() === 6) {
this.calendarData.push(week);
week = [];
}
currentDate.setDate(currentDate.getDate() + 1);
}
if (week.length > 0) {
this.calendarData.push(week);
}
// Check if the last week array has fewer than 7 elements
const lastWeek = this.calendarData[this.calendarData.length - 1];
const remainingCells = 7 - lastWeek.length;
if (remainingCells > 0) {
// Add empty objects to fill the remaining cells
for (let i = 0; i < remainingCells; i++) {
lastWeek.push({});
}
}
this.calendarData.forEach((item) => {
if (item && item.length > 0) {
item.forEach((s) => {
s.info = s.schState == 1 ? "有" : s.schState == 0 ? "满" : "无";
s.pkSchs = s.pkSchs
});
}
});
console.log(this.calendarData, 'this.calendarData')
},
getScheduleState(date) {
const scheduleItem = this.scheduleData.find(item => item.dateWork === date);
return scheduleItem ? scheduleItem.schState : 0;
},
selectDate(day) {
this.selectedDate = day;
const additionalData = this.scheduleData.find(item => item.dateWork === day.date);
console.log(additionalData, 'additionalData')
this.$emit('selceted', additionalData);
// this.$emit('selceted', day)
},
isDateSelected(day) {
return this.selectedDate && day.date === this.selectedDate.date;
},
formatDateLabel(date) {
const month = date.getMonth() + 1;
const day = date.getDate();
return `${this.padZero(month)}-${this.padZero(day)}`;
},
padZero(num) {
return num < 10 ? `0${num}` : `${num}`;
},
},
};
</script>
<style scoped lang="scss">
.calendar {
display: flex;
flex-direction: column;
font-family: Arial, sans-serif;
.selsct-date {
text-align: center;
margin: 20rpx auto;
}
}
.weekdays {
display: flex;
justify-content: space-around;
// background-color: #f2f2f2;
padding: 10rpx;
// border-bottom: 1px solid #ccc;
.weekday {
text-align: center;
padding: 5rpx;
font-weight: bold;
flex: 1;
}
}
.calendar-body {
display: flex;
flex-wrap: wrap;
justify-content: center;
padding: 0 10rpx;
}
.day {
position: relative;
text-align: center;
padding: 10rpx 0;
cursor: pointer;
box-sizing: border-box;
flex: 1;
.day-label {
font-size: 28rpx;
// font-weight: bold;
}
.day-status-has {
width: 40rpx;
height: 40rpx;
color: #4AB039;
opacity: 0.8;
background-color: #EDF8EC;
border-radius: 50%;
text-align: center;
line-height: 40rpx;
border-radius: 50%;
box-sizing: border-box;
margin: auto;
}
.day-status-over {
width: 40rpx;
height: 40rpx;
color: #EA4070;
opacity: 0.8;
background-color: #EFEFEF;
border-radius: 50%;
text-align: center;
line-height: 40rpx;
border-radius: 50%;
box-sizing: border-box;
margin: auto;
}
.day-status-none {
width: 40rpx;
height: 40rpx;
color: rgb(102, 102, 102);
opacity: 0.8;
background-color: #EFEFEF;
border-radius: 50%;
text-align: center;
line-height: 40rpx;
border-radius: 50%;
box-sizing: border-box;
margin: auto;
}
&.selected {
background-color: #85af8b;
color: #fff;
}
}
.week {
display: flex;
flex-wrap: wrap;
}
</style>
2、引入
<view class="calendar-box" v-if="showCalendar">
<u-popup v-model="showCalendar" safe-area-inset-bottom mode="bottom">
<data-calendar :scheduleData="selectedList" @selceted="selcetedDate"></data-calendar>
</u-popup>
</view>