自定义 vant 的 van-calendar 日历控件

最近在做 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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值