最近在做 vue 微信公众号项目, 有个自定义日历控件展示的需求,经过查阅资料,最终实现了如图所示效果,这里做了总结,需要的小伙伴可以参考一下:
HTML代码:
<template>
<div class="pageContainer">
<div class="vanCalendar">
<div class="topTitle">
<div class="topYear">{{ new Date().getFullYear() }}</div>
{{ new Date().getMonth() + 1 }}月
</div>
<van-calendar
ref="calendar"
color="#1989fa"
:formatter="formatter"
:min-date="minDate"
:max-date="maxDate"
:show-title="false"
:show-mark="false"
:show-subtitle="false"
:poppable="false"
:show-confirm="false"
@select="onCalendarSelect"
/>
</div>
</div>
</template>
JS代码:
<script>
export default {
data() {
return {
dateList: [],
minDate: "",
maxDate: "",
};
},
created() {
const currentDate = new Date();
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
this.minDate = new Date(year, month, 1);
this.maxDate = new Date(year, month, this.getLastDayOfMonth());
// 模拟异步请求
setTimeout(() => {
this.dateList = [
{ date: "2024/06/01", status: "0" },
{ date: "2024/06/02", status: "0" },
{ date: "2024/06/03", status: "1" },
{ date: "2024/06/04", status: "1" },
{ date: "2024/06/05", status: "2" },
{ date: "2024/06/06", status: "2" },
{ date: "2024/06/07", status: "2" },
{ date: "2024/06/08", status: "2" },
{ date: "2024/06/09", status: "2" },
{ date: "2024/06/10", status: "1" },
{ date: "2024/06/11", status: "1" },
{ date: "2024/06/12", status: "1" },
{ date: "2024/06/13", status: "1" },
{ date: "2024/06/14", status: "1" },
{ date: "2024/06/15", status: "0" },
{ date: "2024/06/16", status: "0" },
{ date: "2024/06/17", status: "1" },
{ date: "2024/06/18", status: "1" },
{ date: "2024/06/19", status: "1" },
{ date: "2024/06/20", status: "1" },
{ date: "2024/06/21", status: "1" },
{ date: "2024/06/22", status: "0" },
{ date: "2024/06/23", status: "0" },
{ date: "2024/06/24", status: "2" },
{ date: "2024/06/25", status: "2" },
{ date: "2024/06/26", status: "1" },
{ date: "2024/06/27", status: "1" },
{ date: "2024/06/28", status: "1" },
{ date: "2024/06/29", status: "0" },
{ date: "2024/06/30", status: "0" },
];
});
},
methods: {
// 自定义日期文案
formatter(day) {
let isHasData = 0;
let dayTimestamp = this.formattedDateFunc(day.date);
this.dateList.forEach((item) => {
if (dayTimestamp == item.date) {
isHasData = item.status;
}
});
// status=1,日期下方添加黄点
if (isHasData == 1) {
day.className = "addOrangeDot";
}
// status=2,日期下方添加绿点
if (isHasData == 2) {
day.className = "addGreenDot";
}
// 当前选中的日期
if (day.type == "selected") {
if (isHasData == 1) {
// 给选中的日期加上蓝色实心圆,且status=1,日期下方添加黄点
day.className = "selectedDay addOrangeDot";
}
if (isHasData == 2) {
// 给选中的日期加上蓝色实心圆,且status=2,日期下方添加绿点
day.className = "selectedDay addGreenDot";
}
}
// 当天日期
if (dayTimestamp == this.formattedDateFunc()) {
if (isHasData == 1) {
// 给当天加上蓝色空心圆,且status=1,日期下方添加黄点
day.className = "addOrangeDot calendarToday";
}
if (isHasData == 2) {
// 给当天加上蓝色空心圆,且status=2,日期下方添加绿点
day.className = "addGreenDot calendarToday";
}
}
return day;
},
// 日期被选中时触发的方法
onCalendarSelect(val) {
this.$toast("当前选中日期:" + this.formattedDateFunc(val, "-"));
},
// 获取当月的最后一天
getLastDayOfMonth() {
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth();
const lastDay = new Date(year, month + 1, 0).getDate();
return lastDay;
},
// 日期格式化
formattedDateFunc(timestamp, type = "/") {
const currentDate = timestamp ? new Date(timestamp) : new Date();
const year = currentDate.getFullYear();
let month = currentDate.getMonth() + 1;
let day = currentDate.getDate();
month = month < 10 ? `0${month}` : month;
day = day < 10 ? `0${day}` : day;
return `${year}${type}${month}${type}${day}`;
},
},
};
</script>
CSS代码:
<style lang="scss" scoped>
.pageContainer {
height: calc(100vh - 68px);
background: #fff;
font-size: 18px;
overflow: auto;
.vanCalendar {
::v-deep .van-calendar__month-title {
display: none;
}
::v-deep .van-calendar__header {
box-shadow: none;
}
//有数据日期加点
.addGreenDot,
.addOrangeDot {
position: relative;
}
// 绿点
::v-deep .addGreenDot::after {
position: absolute;
content: "";
width: 6px;
height: 6px;
top: 56px;
left: 25px;
border-radius: 50%;
background-color: rgb(34, 177, 76);
}
// 黄点
::v-deep .addOrangeDot::after {
position: absolute;
content: "";
width: 6px;
height: 6px;
top: 56px;
left: 25px;
border-radius: 50%;
background-color: #ff822c;
}
//当天日期
::v-deep .calendarToday {
position: relative;
}
// 当天日期添加空心蓝色圆
::v-deep .calendarToday::before {
width: 40px;
height: 40px;
line-height: 40px;
position: absolute;
top: 11px;
left: 9px;
content: "";
text-align: center;
font-size: 30px;
border-radius: 50%;
border: 2px solid rgb(25, 137, 250);
}
//选中的日期
::v-deep .selectedDay {
position: relative;
}
::v-deep .selectedDay::before {
width: 40px;
height: 40px;
line-height: 40px;
position: absolute;
top: 12px;
left: 8.6px;
content: "";
text-align: center;
font-size: 30px;
border-radius: 50%;
border: none;
}
//选中的日期添加实心蓝色圆
::v-deep .van-calendar__selected-day {
border-radius: 50%;
background: #59afff;
z-index: 2;
position: absolute;
border: none;
}
::v-deep .van-calendar__selected-day::after {
background-color: #fff !important;
}
::v-deep .van-calendar__header-subtitle {
display: none;
}
::v-deep .van-calendar__selected-day {
width: 40px;
height: 40px;
}
}
.topTitle {
position: relative;
padding: 10px;
text-align: center;
background: #fff;
font-size: 24px;
font-weight: bold;
}
.topYear {
position: absolute;
left: 0;
font-weight: normal;
}
}
</style>