js日历组件

在这里插入图片描述

<template>
  <div>
    <Row>
      <div class="flex">
        <Select v-model="currentYear" size="large" class="m-r-10 w-102 high-search-lingHeight" @on-change="changeYear">
          <Option v-for="(item, index) in yearList" :value="item.value" :key="index">
            {{ item.label }}
          </Option>
        </Select>
        <Icon type="ios-arrow-back" class="m-r-10 cut-switch" @click="pickPre(currentYear, currentMonth)" />
        <Select v-model="currentMonth" size="large" class="w-102 high-search-lingHeight" @on-change="changeMonth">
          <Option v-for="(item, index) in monthList" :value="item.value" :key="index">
            {{ item.label }}
          </Option>
        </Select>
        <Icon type="ios-arrow-forward" class="m-l-10 cut-switch" @click="pickNext(currentYear, currentMonth)" />

        <Button size="large" class="m-l-10 customButton" @click="goBackToday">返回今天</Button>

        {{ current.currentYear }}{{ current.currentMonth }}{{ current.currentDay }} {{ current.currentWeek }}
      </div>
    </Row>
    <Row>
      <Col span="18">
        <div clasa="calendar">
          <ul class="weekdays">
            <li v-for="(item, index) in week" :key="index">
              {{ item }}
            </li>
          </ul>
          <!-- 日期 -->
          <ul class="days">
            <li
              v-for="(dayobject, index) in days"
              :key="index"
              :class="{
                'active-boder': dayobject.activeBoder,
              }"
            >
              <!-- 当前天及未来的日期 -->
              <!-- 年月日大于等于当前年月日  年月大于当前年月  年大于当前年-->
              <template v-if="judgeDate(dayobject)">
                <div class="w-100 h-100 p-r c-p" :class="{ 'bg-gray': dayobject.isGray }" @click="clickDate(dayobject, index)">
                  <div class="flex">
                    <span class="m-l-5">
                      <Checkbox v-model="dayobject.isGray" v-if="isCheckBox"></Checkbox>
                    </span>
                  </div>
                  <p class="date-text p-a">
                    <span class="span-text m-b-10">{{ dayobject.day.getDate() }}</span>
                    <span class="span-bg-zwpb">暂未排班</span>
                  </p>
                </div>
              </template>
              <!-- 过去的日期 -->
              <template v-else>
                <div class="w-100 h-100 p-r" :class="dayobject.list ? 'c-p' : ''" @click="clickDate(dayobject, index)">
                  <p class="date-text p-a">
                    <span class="span-text m-b-10" style="color: #e1e1e1">
                      {{ dayobject.day.getDate() }}
                    </span>
                    <span class="span-bg-wpb">未排班</span>
                  </p>
                </div>
              </template>
            </li>
          </ul>
        </div>
      </Col>
    </Row>
  </div>
</template>

<script>
import dayjs from "dayjs";
require("dayjs/locale/zh-cn");
export default {
  data() {
    return {
      week: ["一", "二", "三", "四", "五", "六", "日"],
      days: [],
      currentDay: 1,
      currentMonth: 0,
      currentYear: 0,
      currentWeek: 1,
      current: {
        currentDay: dayjs().format("DD"),
        currentYear: dayjs().format("YYYY"),
        currentMonth: dayjs().format("MM"),
        currentWeek: dayjs().locale("zh-cn").format("dddd"),
      },
      yearList: [
        { value: 2022, label: "2022" },
        { value: 2023, label: "2023" },
        { value: 2024, label: "2024" },
        { value: 2025, label: "2025" },
        { value: 2026, label: "2026" },
        { value: 2027, label: "2027" },
        { value: 2028, label: "2028" },
        { value: 2029, label: "2029" },
        { value: 2030, label: "2030" },
        { value: 2031, label: "2031" },
        { value: 2032, label: "2032" },
      ],
      monthList: [
        { value: 1, label: "1" },
        { value: 2, label: "2" },
        { value: 3, label: "3" },
        { value: 4, label: "4" },
        { value: 5, label: "5" },
        { value: 6, label: "6" },
        { value: 7, label: "7" },
        { value: 8, label: "8" },
        { value: 9, label: "9" },
        { value: 10, label: "10" },
        { value: 11, label: "11" },
        { value: 12, label: "12" },
      ],
    };
  },
  computed: {
    judgeDate() {
      return (dayobject) => {
        //  当前天及未来的日期判断
        // 年月日大于等于当前年月日  年月大于当前年月  年大于当前年
        return (
          (dayobject.day.getFullYear() >= new Date().getFullYear() &&
            dayobject.day.getMonth() >= new Date().getMonth() &&
            dayobject.day.getDate() >= new Date().getDate()) ||
          (dayobject.day.getFullYear() >= new Date().getFullYear() && dayobject.day.getMonth() > new Date().getMonth()) ||
          dayobject.day.getFullYear() > new Date().getFullYear()
        );
      };
    },
  },
  mounted() {
    this.initData(null);
  },
  methods: {
    // 返回今天
    goBackToday() {
      this.initData(null);
      this.current.currentDay = dayjs().format("DD");
      this.current.currentYear = dayjs().format("YYYY");
      this.current.currentMonth = dayjs().format("MM");
      this.current.currentWeek = dayjs().locale("zh-cn").format("dddd");
      this.days.forEach((item) => (item.isGray = false));
    },
    // 切换年份
    changeYear(val) {
      if (val > this.currentYear) {
        this.pickNext(val, this.currentMonth + 1);
      } else if (this.currentMonth === 12) {
        this.pickNext(val, this.currentMonth - 1);
      } else {
        this.pickPre(val, this.currentMonth + 1);
      }
    },
    // 切换月份
    changeMonth(val) {
      if (val > this.currentMonth) {
        this.pickNext(this.currentYear, val + 1);
      } else if (val === 12) {
        this.pickNext(this.currentYear, val - 1);
      } else {
        this.pickPre(this.currentYear, val + 1);
      }
    },
    pickPre(year, month) {
      if (year === 2022 && month === 1)
        return this.$Message.error({
          content: "无2022年以前的数据",
          duration: 5,
        });
      var d = new Date(this.formatDate(year, month, 1));
      d.setDate(0);
      this.initData(this.formatDate(d.getFullYear(), d.getMonth() + 1, 1));
    },
    pickNext(year, month) {
      if (year === 2032 && month === 12)
        return this.$Message.error({
          content: "无2032年以后的数据",
          duration: 5,
        });
      var d = new Date(this.formatDate(year, month, 1));
      d.setDate(35);
      this.initData(this.formatDate(d.getFullYear(), d.getMonth() + 1, 1));
    },
    // 点击今天以及未来日期
    clickDate(val, index) {
      this.setCurrent(val, index);
    },
    setCurrent(val, index) {
      this.current.currentDay = dayjs(val.day).format("DD");
      this.current.currentYear = dayjs(val.day).format("YYYY");
      this.current.currentMonth = dayjs(val.day).format("MM");
      this.current.currentWeek = dayjs(val.day).locale("zh-cn").format("dddd");
      this.days.forEach((item) => (item.activeBoder = false));
      this.days[index].activeBoder = true;
    },
    initData(cur) {
      var date = cur ? new Date(cur) : this.getFirstDayOfNextMonth();
      this.setCurrentDate(date);
      this.days.length = 0;
      this.initCurrentWeekDays();
      this.initOtherWeeksDays();
    },
    getFirstDayOfNextMonth() {
      var now = new Date();
      var d = new Date(this.formatDate(now.getFullYear(), now.getMonth() + 1, 1));
      d.setDate(35);
      var date = new Date(this.formatDate(d.getFullYear(), d.getMonth(), 1));
      console.log(dayjs(date).format("YYYY-MM-DD"));
      return date;
    },
    setCurrentDate(date) {
      this.currentDay = date.getDate();
      this.currentYear = date.getFullYear();
      this.currentMonth = date.getMonth() + 1;
      this.currentWeek = date.getDay();
      if (this.currentWeek === 0) {
        this.currentWeek = 7;
      }
    },
    initCurrentWeekDays() {
      for (var i = this.currentWeek - 1; i >= 0; i--) {
        const dayobject = this.newDayObject(i);
        this.days.push(dayobject);
      }
    },
    initOtherWeeksDays() {
      for (var i = 1; i <= 35 - this.currentWeek; i++) {
        const dayobject = this.newDayObject(i, true);
        this.days.push(dayobject);
      }
    },
    newDayObject(i, isNotCurrentWeek = false) {
      var d = new Date(this.formatDate(this.currentYear, this.currentMonth, this.currentDay));
      d.setDate(d.getDate() + (isNotCurrentWeek ? i : -i));
      var dayobject = {
        day: d,
        isGray: false,
        dayPt: dayjs(d).format("YYYY-MM-DD"),
        activeBoder: this.isActiveBorder(d),
      };
      return dayobject;
    },
    isActiveBorder(d) {
      return (
        dayjs(d).format("YYYY-MM-DD") === dayjs().format("YYYY-MM-DD") ||
        dayjs(d).format("YYYY-MM-DD") ===
          dayjs(this.current.currentYear + "-" + this.current.currentMonth + "-" + this.current.currentDay).format("YYYY-MM-DD")
      );
    },
    formatDate(year, month, day) {
      var y = year;
      var m = month;
      if (m < 10) m = "0" + m;
      var d = day;
      if (d < 10) d = "0" + d;
      return y + "-" + m + "-" + d;
    },
  },
};
</script>

<style lang="less" scoped>
.calendar {
  width: 100%;
  margin: 0 auto;

  ul {
    list-style: none;
    padding: 0;
    margin: 0;
  }
}

.month ul li {
  box-sizing: border-box;
  color: white;
  font-size: 20px;
  text-transform: uppercase;
  letter-spacing: 3px;
}

.weekdays {
  display: flex;
  flex-wrap: wrap;
  color: #000;
}

.weekdays li {
  box-sizing: border-box;
  display: inline-block;
  width: 14.2%;
  height: 70px;
  line-height: 70px;
  border: 1px solid #dcdcdc;
  text-align: center;
}

.days {
  background: #ffffff;
  display: flex;
  flex-wrap: wrap;
}

.days li {
  list-style-type: none;
  width: 14.2%;
  height: 140px;
  border: 1px solid #dcdcdc;
  display: inline-block;
  text-align: center;
  font-size: 1rem;
  color: #000;
}

.active-boder {
  border: 2px solid rgba(72, 189, 160, 1) !important;
}

.days li .other-month {
  color: gainsboro;
}

.flex {
  display: flex;
  justify-content: space-between;

  .bg-color {
    background-color: rgba(221, 221, 221, 1);
    color: #ffffff;
    width: 60px;
    text-align: center;
    height: 20px;
    font-size: 10px;
    transform: scale(0.83333) translate(10%, 0%);
    border: 1px solid rgba(221, 221, 221, 1);
    border-bottom-left-radius: 50px;
  }

  .opacity {
    opacity: 0;
  }
}

.date-text {
  width: 100px;
  height: 50px;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  text-align: center;

  .span-text {
    display: block;
  }

  .span-bg {
    color: #ffffff;
    width: 22px;
    height: 20px;
    border-radius: 50%;
    display: inline-block;
  }

  .span-bg-zwpb {
    color: #ffffff;
    width: 90px;
    height: 22px;
    border-radius: 40%;
    display: inline-block;
    background-color: #dcdcdc;
  }

  .span-bg-wpb {
    color: #ffffff;
    width: 70px;
    height: 22px;
    border-radius: 40%;
    display: inline-block;
    background-color: #dcdcdc;
  }
}

.bg-yellow {
  background-color: rgba(251, 169, 52, 1);
}

.bg-green {
  background-color: rgba(169, 227, 90, 1);
}

.bg-blue {
  background-color: rgba(51, 153, 255, 1);
}

.bg-gray {
  border-color: #e1e1e1;
}

.c-color {
  color: #999999 !important;
}
.cut-switch {
  display: inline-block;
  cursor: pointer;
  position: relative;
  top: 8px;
}
</style>

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值