elementui日历显示红点及根据日程范围判断是否有红点
生成指定日期范围内的所有日期
generateDateRange(startStr, endStr) {const dates = []; 日期列表const start = new Date(startStr); 日程开始日期const end = new Date(endStr); 日程结束日期end.setHours(23, 59, 59, 999); 结束的那一天设置为23点59分59秒// 生成日期范围内的所有日期let currentDate = new Date(start); 判断天数设置为日程开始日期while (currentDate <= end) {const dateStr = this.formatDate(currentDate); dates.push(dateStr); 如果当前判断的日期在日程范围内就加入日期列表currentDate.setDate(currentDate.getDate() + 1); 日期判断天数加1}return dates;},// 格式化日期为 'YYYY-MM-DD' 字符串formatDate(date) {const year = date.getFullYear();const month = String(date.getMonth() + 1).padStart(2, '0');const day = String(date.getDate()).padStart(2, '0');return `${year}-${month}-${day}`;},
// 生成所有日期范围内的日期
// 生成所有日期范围内的日期generateDateRanges() {const allDates = [];this.backendDateRanges.forEach(range => {const startStr = this.convertDateformat(range.start);const endStr = this.convertDateformat(range.end);const dates = this.generateDateRange(startStr, endStr);allDates.push(...dates);});// 去重this.selectedDates = [...new Set(allDates)];},
// 判断当前日期是否在选定日期范围内
isSelectedDate(day) {return this.selectedDates.includes(day);},
// 显示某天的日程列表
showEvents(day) {this.currentDay = day;this.currentDayEvents = this.backendDateRanges.filter(range => {const startStr = this.convertDateformat(range.start);const endStr = this.convertDateformat(range.end);const start = new Date(startStr);const end = new Date(endStr);const current = new Date(day);// 设置结束日期为当天的最后时刻,以确保包含结束日期end.setHours(23, 59, 59, 999);return current >= start && current <= end;});}
完整代码
<template><div><el-calendar v-model="value" style="width: 30%;height: 50%;" ><!-- 自定义日期单元格插槽 --><template slot="dateCell" slot-scope="{ data }"><div @click="showEvents(data.day)"><!-- 显示日期 --><div class="date-content">{{ data.day.split('-').slice(2).join('-') }}</div><!-- 如果日期在 selectedDates 中,显示红点 --><div v-if="isSelectedDate(data.day)" class="dot"></div></div></template></el-calendar><!-- 显示日程列表 --><div v-if="currentDayEvents.length > 0" class="events-list" style="width: 30%;height: 50%;" ><h3>日程列表 ({{ currentDay }})</h3><ul><li v-for="event in currentDayEvents" :key="event.id">{{ event.title }}</li></ul></div></div>
</template><script>export default {data() {return {value: new Date(),backendDateRanges: [{id: 1,title: '日程1',start: '2025/03/01',end: '2025/04/06'},{id: 2,title: '日程2',start: '2025/04/02',end: '2025/04/10'}],// 动态生成的选定日期数组selectedDates: [],// 当前点击日期的日程列表currentDayEvents: [],// 当前点击的日期currentDay: ''};},mounted() {// 在组件挂载后生成选定日期范围this.generateDateRanges();},methods: {myEcharts(){//var myChart = this.$echarts.init(document.getElementById('main'));},// 将后端传过来的日期格式转换为 YYYY-MM-DDconvertDateformat(dateStr) {return dateStr.split('/').join('-');},// 生成指定日期范围内的所有日期generateDateRange(startStr, endStr) {const dates = [];const start = new Date(startStr);const end = new Date(endStr);end.setHours(23, 59, 59, 999);// 生成日期范围内的所有日期let currentDate = new Date(start);while (currentDate <= end) {const dateStr = this.formatDate(currentDate);dates.push(dateStr);currentDate.setDate(currentDate.getDate() + 1);}return dates;},// 格式化日期为 'YYYY-MM-DD' 字符串formatDate(date) {const year = date.getFullYear();const month = String(date.getMonth() + 1).padStart(2, '0');const day = String(date.getDate()).padStart(2, '0');return `${year}-${month}-${day}`;},// 生成所有日期范围内的日期generateDateRanges() {const allDates = [];this.backendDateRanges.forEach(range => {const startStr = this.convertDateformat(range.start);const endStr = this.convertDateformat(range.end);const dates = this.generateDateRange(startStr, endStr);allDates.push(...dates);});// 去重this.selectedDates = [...new Set(allDates)];},// 判断当前日期是否在选定日期范围内isSelectedDate(day) {return this.selectedDates.includes(day);},// 显示某天的日程列表showEvents(day) {this.currentDay = day;this.currentDayEvents = this.backendDateRanges.filter(range => {const startStr = this.convertDateformat(range.start);const endStr = this.convertDateformat(range.end);const start = new Date(startStr);const end = new Date(endStr);const current = new Date(day);// 设置结束日期为当天的最后时刻,以确保包含结束日期end.setHours(23, 59, 59, 999);return current >= start && current <= end;});}}
};
</script><style scoped>
.date-content {margin-bottom: 5px;}.dot {width: 6px;height: 6px;background-color: red;border-radius: 50%;display: inline-block;
}.events-list {margin-top: 20px;padding: 10px;background-color: #f5f5f5;border-radius: 5px;
}.events-list h3 {margin-top: 0;
}.events-list ul {list-style-type: none;padding: 0;
}.events-list li {padding: 5px 0;
}
</style>