vue 封装日历组件

父组件:

		<div class="calendar">
			<Calendar
				ref="calendar"
				:date="new Date()"
				@enter="mouseenter"
				@leave="mouseleave"
				@changeMonth="changeMonth"
				@startTime="queryStartTime"
				@endTime="queryEndTime"
				style="width:100%;height:350px"
			>
				<!-- 可使用动态插槽名设置,v-slot:[slotName] -->
				<!-- <template v-slot:2021-5-21>
					<div style="position:absolute;bottom:-20px">今天</div>
				</template> -->
			</Calendar>
  	</div>
  	

日历组件:

<template>
  <div class="cal_con">
    <div class="cal_header">
      <div class="cal_h_left">
        <span class="cal_h_time">{{ year }}{{ month }}</span>
      </div>
      <div class="cal_h_right">
        <div class="cal_h_btn" @click="preMonth">
          <img src="submodule/ccp/assets/images/up_icon_1.png" />
        </div>
        <div class="cal_h_btn" @click="nextMonth">
          <img src="submodule/ccp/assets/images/down_icon_1.png" />
        </div>
      </div>
    </div>
    <div class="cal_month">
      <div class="cal_m_weeks">
        <span v-for="item in weeks" :key="item" class="cal_m_day_cell">{{ item }}</span>
      </div>
      <div class="cal_m_days">
        <div
          v-for="(ds, index) in monthData"
          :key="index"
          class="cal_m_day_line"
        >
          <div
            v-for="item in ds"
            :key="item.day"
            :style="{
              color: getCellColor(item),
              background: getCellBackgroundColor(item),
              'border-radius': getBorderRadius(item),
            }"
            @mouseenter="mouseenter(item, $event)"
            @mouseleave="mouseleave(item, $event)"
            @click="selectDateTime(item)"
            :class="[
              'cal_m_day_cell',
              {
                // today: todayTime === day.time,
                // 'before-day': day.time < todayTime,
                'select-start':
                  item.date && item.date.getTime() == selectTime.start,
                'select-end':
                  item.date && item.date.getTime() == selectTime.end,
                select:
                  item.date &&
                  item.date.getTime() > selectTime.start &&
                  item.date.getTime() < selectTime.end,
              },
            ]"
          >
            <div class="date">{{ item.day }}</div>
            <slot
              :name="item.fullYear + '-' + item.month + '-' + item.day"
            ></slot>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "Calendar",
  props: {
    date: {
      type: Date,
      default: () => new Date(),
    },
  },
  data() {
    return {
      now: this.date,
      year: 0,
      month: 0,
      weeks: ["日", "一", "二", "三", "四", "五", "六"],
      monthData: [],
      currentYear: new Date().getFullYear(),
      currentMonth: new Date().getMonth() + 1,
      currentDay: new Date().getDate(),
      /**新加*/
      todayTime: "",
      selectTime: {
        start: "",
        end: "",
      },
      /***/
    };
  },
  computed: {},
  async mounted() {
    this.setYearMonth(this.now);
    await this.generateMonth(this.now);
    console.log("===monthData====", this.monthData);
  },
  methods: {
    selectDateTime(time) {
      // console.log("===time===", time);
      // console.log("===monthData====", this.monthData);
      // if (time < this.todayTime) {
      //   return false;
      // }
      if (!this.selectTime.start && !this.selectTime.end) {
        this.selectTime.start = time.date.getTime();
      } else if (this.selectTime.start && this.selectTime.end) {
        this.selectTime.start = time.date.getTime();
        this.selectTime.end = "";
      } else if (
        this.selectTime.start &&
        this.selectTime.start < time.date.getTime()
      ) {
        this.selectTime.end = time.date.getTime();
      } else if (
        this.selectTime.start &&
        this.selectTime.start > time.date.getTime()
      ) {
        this.selectTime.start = time.date.getTime();
        this.selectTime.end = "";
      }
      if (this.selectTime.start) {
        this.$emit("startTime", this.selectTime.start);
      }
      if (this.selectTime.end) {
        this.$emit("endTime", this.selectTime.end);
      }
    },

    setYearMonth(now) {
      this.year = now.getFullYear();
      this.month = now.getMonth() + 1;
    },
    preYear() {
      let n = this.now;
      let date = new Date(
        n.getFullYear() - 1,
        n.getMonth(),
        n.getDate(),
        n.getHours(),
        n.getMinutes(),
        n.getSeconds(),
        n.getMilliseconds()
      );
      this.setYearMonthInfos(date);
    },
    preMonth() {
      let n = this.now;
      let date = new Date(
        n.getFullYear(),
        n.getMonth() - 1,
        n.getDate(),
        n.getHours(),
        n.getMinutes(),
        n.getSeconds(),
        n.getMilliseconds()
      );
      this.setYearMonthInfos(date);
    },
    nextYear() {
      let n = this.now;
      let date = new Date(
        n.getFullYear() + 1,
        n.getMonth(),
        n.getDate(),
        n.getHours(),
        n.getMinutes(),
        n.getSeconds(),
        n.getMilliseconds()
      );

      this.setYearMonthInfos(date);
    },
    nextMonth() {
      let n = this.now;
      let date = new Date(
        n.getFullYear(),
        n.getMonth() + 1,
        n.getDate(),
        n.getHours(),
        n.getMinutes(),
        n.getSeconds(),
        n.getMilliseconds()
      );

      this.setYearMonthInfos(date);
    },
    setYearMonthInfos(date) {
      this.setYearMonth(date);
      this.generateMonth(date);
      this.now = date;
      this.dateChange();
    },
    generateMonth(date) {
      date.setDate(1);
      // 星期 0 - 6, 星期天 - 星期6
      let weekStart = date.getDay();

      let endDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
      let dayEnd = endDate.getDate();
      // 星期 0 - 6, 星期天 - 星期6
      let weeEnd = endDate.getDay();

      let milsStart = date.getTime();
      let dayMils = 24 * 60 * 60 * 1000;
      let milsEnd = endDate.getTime() + dayMils;

      let monthDatas = [];
      let current;
      // 上个月的几天
      for (let i = 0; i < weekStart; i++) {
        current = new Date(milsStart - (weekStart - i) * dayMils);
        monthDatas.push({
          type: -1,
          date: current,
          fullYear: current.getFullYear(),
          month: current.getMonth() + 1,
          day: current.getDate(),
        });
      }
      // 当前月
      for (let i = 0; i < dayEnd; i++) {
        current = new Date(milsStart + i * dayMils);
        monthDatas.push({
          type: 0,
          date: current,
          fullYear: current.getFullYear(),
          month: current.getMonth() + 1,
          day: current.getDate(),
        });
      }
      // 下个月的几天
      for (let i = 0; i < 6 - weeEnd; i++) {
        current = new Date(milsEnd + i * dayMils);
        monthDatas.push({
          type: 1,
          date: current,
          fullYear: current.getFullYear(),
          month: current.getMonth() + 1,
          day: current.getDate(),
        });
      }

      this.monthData = [];
      for (let i = 0; i < monthDatas.length; i++) {
        let mi = i % 7;
        if (mi == 0) {
          this.monthData.push([]);
        }
        this.monthData[Math.floor(i / 7)].push(monthDatas[i]);
      }

      // 少于6行,补足6行
      if (this.monthData.length <= 5) {
        milsStart = current.getTime();
        let lastLine = [];
        for (let i = 1; i <= 7; i++) {
          current = new Date(milsStart + i * dayMils);
          lastLine.push({
            type: 1,
            date: current,
            fullYear: current.getFullYear(),
            month: current.getMonth() + 1,
            day: current.getDate(),
          });
        }
        this.monthData.push(lastLine);
      }
    },

    getCellColor(d) {
      if (
        d.fullYear == this.currentYear &&
        d.month == this.currentMonth &&
        d.day == this.currentDay
      ) {
        return "#409eff";
      }
      // let color = d.type == -1 ? "#c0c4cc" : d.type == 1 ? "#c0c4cc  " : "";
      // return color;
    },
    getCellBackgroundColor(d) {
      if (
        d.fullYear == this.currentYear &&
        d.month == this.currentMonth &&
        d.day == this.currentDay
      ) {
        return "rgba(220,235,253,0.80)";
      }
    },
    getBorderRadius(d) {
      if (
        d.fullYear == this.currentYear &&
        d.month == this.currentMonth &&
        d.day == this.currentDay
      ) {
        return "2px";
      }
    },
    mouseenter(d, event) {
      this.$emit("enter", event, d);
    },
    mouseleave(d, event) {
      this.$emit("leave", event, d);
    },
    dateChange() {
      let fullYear = this.now.getFullYear();
      let month = this.now.getMonth();

      let startDay = new Date(fullYear, month, 1);
      let endDay = new Date(fullYear, month + 1, 0, 23, 59, 59);
      this.$emit("changeMonth", startDay, endDay);
    },
  },
};
</script>

<style scoped lang="scss">
.cal_con {
  width: 100%;
  height: 100%;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  color: #606266;

  background: #fff;
  border-radius: 4px;
  margin: auto;

  .cal_header {
    height: 24px;
    padding: 5px;
    font-size: 14px;
    line-height: 24px;
    display: flex;
    justify-content: space-between;
    justify-items: center;

    .cal_h_time {
      display: inline-block;
      font-family: MicrosoftYaHei-Bold;
      font-size: 18px;
      color: #363232;
      letter-spacing: 0;
      font-weight: 700;
    }
    .cal_h_time:hover {
      color: #409eff;
    }

    .cal_h_right {
      height: 100%;
      display: flex;
      .cal_h_btn {
        height: 100%;
        width: 24px;
        cursor: pointer;
        margin-left: 0.5rem;
        img {
          width: 1rem;
          height: 0.6rem;
        }
      }
      // .cal_h_btn:hover {
      // background-color: #ebeef5;
      // }
      .cal_h_l_icon {
        height: 16px;
        width: 16px;
        margin: auto;
        text-align: center;
      }
    }
  }

  .cal_month {
    font-size: 12px;
    text-align: center;
    height: calc(100% - 34px);

    .cal_m_day_cell {
      width: 60%;
      height: 60%;
      line-height: 100%;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .cal_m_day_cell:hover {
      color: #409eff;
      font-weight: 600;
      // background: rgba(220,235,253,0.80);
    }

    /**新加*/
    .select-start,
    .select-end {
      // background: rgba(255, 92, 52, 1);
      background: #427bf1;
      border-radius: 4.93px;
      .date {
        color: #fff;
        &::before {
          position: absolute;
          top: -30px;
          left: 8px;
          content: "开始";
        }
      }
    }
    .select-end {
      .date {
        &::before {
          content: "结束";
        }
      }
    }
    .select-start {
      .right-side {
        background: #fff3f1;
      }
    }
    .select-end {
      .left-side {
        background: #fff3f1;
      }
    }
    .select {
      // background: #fff3f1;
      background: rgba(220, 235, 253, 0.8);
      border-radius: 2px;
    }
    /**完*/

    .cal_m_weeks {
      height: 16px;
      padding: 8px;
      display: flex;
      justify-content: space-around;
      justify-items: center;
      border-bottom: 1px solid #e4e7ed;
    }

    .cal_m_days {
      height: calc(100% - 49px);
      padding: 8px;
      display: flex;
      justify-content: space-around;
      justify-items: center;
      flex-wrap: wrap;
      .cal_m_day_line {
        width: 100%;
        display: flex;
        justify-content: space-around;
        justify-items: center;
        align-items: center;
      }
    }
  }
}
</style>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值