Vue 日历日程组件

Vue日历日程组件

原文链接 https://www.jb51.net/article/212767.htm
与原文对比修改了太多,不作详细描述

效果预览

在这里插入图片描述

vue组件代码

<template>
  <div class="wh-container">
    <div class="wh-content-all">
      <div class="wh-top-change">
        <span class="wh-arrow-left">
          <i @click="PreYear" class="el-icon-d-arrow-left"></i>
          <i @click="PreMonth" class="el-icon-arrow-left"></i>
        </span>
        <span class="wh-content-li">{{ dateTop }}</span>
        <span class="wh-arrow-right">
          <i @click="NextMonth" class="el-icon-arrow-right"></i>
          <i @click="NextYear" class="el-icon-d-arrow-right"></i>
        </span>
      </div>
      <div class="wh-content">
        <div class="wh-content-item" v-for="(tag,index) in textTop" :key="index">
          <div class="wh-top-tag">{{ tag }}</div>
        </div>
        <div
          class="wh-content-item"
          v-for="(item,index) in dayList" :key="index"
          @click="clickDay(item,index)">
          <div
            class="date-box"
            :class="{'wh-isToday':item.isToday,'wh-choose-day':item.chooseDay,'holiday':item.holiday}">
            <div
              class="wh-item-date"
              :class="{'wh-other-dayHide':item.otherMonth!=='nowMonth','wh-want-dayHide':item.dayHide}">
              {{ item.id }}
            </div>
            <div class="date-sign">
              <i v-if="item.leave"
                 :style="[{background:(item.leave)?'red':''}]"
                 class="sign"></i>
              <i v-if="item.meeting"
                 :style="[{background:(item.meeting)?'rgb(244 184 73)':''}]" class="sign"></i>
              <i v-if="item.business"
                 :style="[{background:(item.business)?'#639af1':''}]"
                 class="sign"></i>
              <i v-if="item.egress"
                 :style="[{background:(item.egress)?'rgb(145,204,117)':''}]"
                 class="sign"></i>
            </div>
          </div>
        </div>
      </div>
      <div class="tags">
        <span><i style="background-color:red;"></i>请假</span>
        <span><i style="background-color:rgb(244,184,73);"></i>会议</span>
        <span><i style="background-color:#639af1;"></i>出差</span>
        <span><i style="background-color:rgb(145,204,117);"></i>外出</span>
      </div>
    </div>
  </div>
</template>
<script>
import timeUtil from "./calendar.js";
import {dateFormat} from "@/util/date";

export default {
  name: "Calendar",
  components: {},
  data() {
    return {
      textTop: ["日", "一", "二", "三", "四", "五", "六"],
      scheduleDialogVisible: false, // 新建日程弹窗
      dayList: [],
      historyChose: [],
      dateTop: "",
      currentDate: new Date(),//当前日期
      leave: [], // 当前月份 请假 日期列表
      meeting: [], // 当前月份 会议 日期列表
      business: [], // 当前月份 出差 日期列表
      egress: [], // 当前月份 外出 日期列表
      attendance: [], // 当前月份 日程列表
      holiday: [], // 节假日
      scheduleEditDialogVisible: false, // 修改日程弹窗
      scheduleData: [] // 修改日程数据
    };
  },
  computed: {},
  mounted() {
    this.getList();
  },
  methods: {
    // 查询日程
    getUserAttendance() {
      this.leave = [
        "2023-09-07",
        "2023-09-08",
        "2023-09-09"
      ]
      this.meeting = [
        "2023-09-08",
        "2023-09-09"
      ]
      this.business = [
        "2023-09-08"
      ]
      this.egress = [
        "2023-09-08",
        "2023-09-07"
      ]
      this.holiday = [
        "2023-09-30",
        "2023-09-29",
        "2023-09-24",
        "2023-09-23",
        "2023-09-17",
        "2023-09-16",
        "2023-09-10",
        "2023-09-09",
        "2023-09-03",
        "2023-09-02"
      ] // 节假日
      this.setDaySign()
    },
    // 点击日期
    clickDay(item) {
      if (item.otherMonth == "preMonth") {
        // 切换至上个月
        this.PreMonth(item.date)
      } else if (item.otherMonth == "nextMonth") {
        // 切换至下个月
        this.NextMonth(item.date)
      } else if (item.otherMonth == "nowMonth") {
        // 如果有日程,则查询
        if (item.leave || item.meeting || item.business || item.egress) {
          // this.searchUserAttendanceList(item)
        }
      }
    },
    PreMonth() {
      this.currentDate = timeUtil.getOtherMonth(this.currentDate, "preMonth");
      this.getList();
    },
    NextMonth() {
      this.currentDate = timeUtil.getOtherMonth(this.currentDate, "nextMonth");
      this.getList();
    },
    PreYear() {
      this.currentDate = timeUtil.getOtherYear(this.currentDate, "preYear");
      this.getList();
    },
    NextYear() {
      this.currentDate = timeUtil.getOtherYear(this.currentDate, "nextYear");
      this.getList();
    },
    async getList() {
      this.dateTop = dateFormat(this.currentDate, "yyyy年MM月");
      this.dayList = timeUtil.getMonthList(this.currentDate);
      // 获取日期后,查询日程
      this.getUserAttendance()
    },
    // 设置日程标记
    setDaySign() {
      for (let index in this.dayList) {
        let item = this.dayList[index]
        item.leave = this.leave.indexOf(item.date) > -1; // 请假
        item.meeting = this.meeting.indexOf(item.date) > -1; // 会议
        item.business = this.business.indexOf(item.date) > -1; // 出差
        item.egress = this.egress.indexOf(item.date) > -1; // 外出
        item.holiday = this.holiday.indexOf(item.date) > -1; // 节假日
      }
      this.dayList.splice(0, 0)
    }
  },
};
</script>
<style scoped lang="scss">
.wh-container {
  padding: 10px;
  height: calc(100% - 20px);

  .wh-content-all {
    background-color: #fff;
    width: 100%;
    overflow: hidden;
    height: calc(100% - 42px);

    .wh-top-change {
      display: flex;
      justify-content: space-around;
      align-items: center;

      span {
        cursor: pointer;
        display: flex;
        color: $main-color-blue;
        font-weight: 700;
        font-size: 16px;
        justify-content: center;
        align-items: center;
        height: 48px;
      }

      .wh-content-li {
        cursor: auto;
        width: 140px;
      }

      .wh-arrow-left, .wh-arrow-right {
        color: #999;
        flex: 1;

        &:active {
          color: $main-color-blue;
        }

        i {
          margin: 0 5px;
        }
      }
    }

    .wh-content {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-around;
      height: calc(100% - 48px - 20px);

      .wh-content-item {
        width: 14%;
        font-size: 16px;
        color: #333;
        //height: 16%;
        display: flex;
        align-items: center;

        .date-box {
          height: 30px;
          width: 30px;
          display: flex;
          align-items: center;
          justify-content: center;
          flex-direction: column;
          cursor: pointer;
          border-radius: 4px;

          &.holiday {
            background: rgba(254, 245, 245, 1);
            color: rgb(235, 51, 51);
          }

          &:hover {
            background: rgba(29, 128, 254, 0.1);
          }

          &.wh-isToday {
            background: rgba(29, 128, 254, 0.1);
            //background: $main-color-blue;
            //border-radius: 4px;
            //color: black;
          }

          .wh-item-date {
            width: 30px;
            //height: 30px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-weight: bold;
          }

          .date-sign {
            //width: 10px;
            height: 6px;
            display: flex;
            //flex-direction: column;
            justify-content: center;
            align-items: center;

            .sign {
              display: inline-block;
              width: 4px;
              height: 4px;
              margin: 1px;
              border-radius: 2px;
            }
          }
        }
      }
    }

    .tags {
      font-size: 12px;
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: center;

      span {
        padding: 0 6px;
        display: flex;
        align-items: center;
        justify-content: center;

        i {
          display: inline-block;
          width: 4px;
          height: 4px;
          border-radius: 2px;
          margin-right: 5px;
        }
      }
    }
  }
}

.calendar-btm {
  cursor: pointer;
  height: 45px;
  color: $main-color-blue;
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid $main-color-blue;
  border-radius: 7px;

  i {
    margin-right: 10px;
  }
}

.wh-content:first-child .wh-content-item-tag,
.wh-content:first-child .wh-content-item {
  color: #ddd;
  font-size: 16px;
}

.wh-top-tag {
  width: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.wh-content-item .wh-other-dayHide {
  color: #bfbfbf;
}

.wh-content-item .wh-want-dayHide {
  color: #bfbfbf;
}


.wh-content-item .wh-choose-day {
  background: #fff;
  color: black;
  //border-radius: 100px;
}
</style>

js代码 calendar.js

import {dateFormat} from "@/util/date";

export default {
  // 当某月的天数
  getDaysInOneMonth(date) {
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const d = new Date(year, month, 0);
    return d.getDate();
  },
  // 向前空几个
  getMonthweek(date) {
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const dateFirstOne = new Date(year + '-' + month + '-1');
    return this.sundayStart ?
      dateFirstOne.getDay() == 0 ? 7 : dateFirstOne.getDay() :
      dateFirstOne.getDay() == 0 ? 6 : dateFirstOne.getDay() - 1;
  },
  /**
   * 获取当前日期上个月或者下个月
   */
  getOtherMonth(date, str = 'nextMonth') {
    const timeArray = this.dateFormat(date).split('-');
    const year = timeArray[0];
    const month = timeArray[1];
    const day = timeArray[2];
    let year2 = year;
    let month2;
    if (str === 'nextMonth') {
      month2 = parseInt(month) + 1;
      if (month2 == 13) {
        year2 = parseInt(year2) + 1;
        month2 = 1;
      }
    } else {
      month2 = parseInt(month) - 1;
      if (month2 == 0) {
        year2 = parseInt(year2) - 1;
        month2 = 12;
      }
    }
    let day2 = day;
    const days2 = new Date(year2, month2, 0).getDate();
    if (day2 > days2) {
      day2 = days2;
    }
    if (month2 < 10) {
      month2 = '0' + month2;
    }
    if (day2 < 10) {
      day2 = '0' + day2;
    }
    const t2 = year2 + '-' + month2 + '-' + day2;
    return new Date(t2);
  },
  /**
   * 获取当前日期上一年或者下一年
   */
  getOtherYear(date, str = 'nextYear') {
    let year = new Date(date).getFullYear();
    let month = new Date(date).getMonth() + 1;
    let day = new Date(date).getDate();
    let month2;
    if (str === 'nextYear') {
      year = parseInt(year) + 1;
    } else {
      year = parseInt(year) - 1;
    }
    let days2 = new Date(year, month, 0).getDate();
    if (day > days2) {
      day = days2;
    }
    if (month < 10) {
      month2 = '0' + month;
    }
    if (day < 10) {
      day = '0' + day;
    }
    const t2 = year + '-' + month2 + '-' + day;
    return new Date(t2);
  },
  // 上个月末尾的一些日期
  getLeftArr(date) {
    const arr = [];
    const leftNum = this.getMonthweek(date);
    const num = this.getDaysInOneMonth(this.getOtherMonth(date, 'preMonth')) - leftNum + 1;
    const preDate = this.getOtherMonth(date, 'preMonth');
    // 上个月多少开始
    for (let i = 0; i < leftNum; i++) {
      const nowTime = this.dateFormat(new Date(preDate.setDate(num + i)));
      arr.push({
        id: num + i,
        date: nowTime,
        isToday: false,
        otherMonth: 'preMonth',
      });
    }
    return arr;
  },
  // 下个月末尾的一些日期
  getRightArr(date) {
    const arr = [];
    const nextDate = this.getOtherMonth(date, 'nextMonth');
    const leftLength = this.getDaysInOneMonth(date) + this.getMonthweek(date);
    const _length = 7 - leftLength % 7;
    for (let i = 0; i < _length; i++) {
      const nowTime = this.dateFormat(new Date(nextDate.setDate(i + 1)));
      arr.push({
        id: i + 1,
        date: nowTime,
        isToday: false,
        otherMonth: 'nextMonth',
      });
    }
    return arr;
  },
  // format日期
  dateFormat(date) {
    return dateFormat(date, "yyyy-MM-dd")
  },
  // 获取某月的列表不包括上月和下月
  getMonthListNoOther(date) {
    const arr = [];
    const num = this.getDaysInOneMonth(date);
    const toDay = this.dateFormat(new Date());
    for (let i = 0; i < num; i++) {
      const nowTime = this.dateFormat(new Date(date.setDate(i + 1)));
      arr.push({
        id: i + 1,
        date: nowTime,
        isToday: toDay == nowTime,
        otherMonth: 'nowMonth',
      });
    }
    return arr;
  },
  // 获取某月的列表 用于渲染
  getMonthList(date) {
    return [...this.getLeftArr(date), ...this.getMonthListNoOther(date), ...this.getRightArr(date)];
  },
  // 默认是周一开始
  sundayStart: true, // 从周日开始
};

时间格式化函数 dateFormat

/**
 * 日期格式化
 */
export function dateFormat(date, format) {
  format = format || 'yyyy-MM-dd hh:mm:ss';
  if (date !== 'Invalid Date') {
    let o = {
      "M+": date.getMonth() + 1, //month
      "d+": date.getDate(), //day
      "h+": date.getHours(), //hour
      "m+": date.getMinutes(), //minute
      "s+": date.getSeconds(), //second
      "q+": Math.floor((date.getMonth() + 3) / 3), //quarter
      "S": date.getMilliseconds() //millisecond
    }
    if (/(y+)/.test(format)) format = format.replace(RegExp.$1,
      (date.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (let k in o)
      if (new RegExp("(" + k + ")").test(format))
        format = format.replace(RegExp.$1,
          RegExp.$1.length === 1 ? o[k] :
            ("00" + o[k]).substr(("" + o[k]).length));
    return format;
  }
  return '';
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于自定义月日历日程组件,你可以使用Vue.js框架来实现。下面是一个简单的示例代码,可以帮助你开始构建这个组件: ```vue <template> <div class="calendar"> <div class="header"> <button @click="previousMonth"><</button> <h2>{{ currentMonth }}</h2> <button @click="nextMonth">></button> </div> <div class="days"> <div v-for="day in days" :key="day" class="day">{{ day }}</div> </div> <div class="events"> <div v-for="event in events" :key="event.id" class="event"> <p>{{ event.date }}</p> <p>{{ event.title }}</p> </div> </div> </div> </template> <script> export default { data() { return { currentMonth: '', days: [], events: [ { id: 1, date: '2022-01-05', title: 'Event 1' }, { id: 2, date: '2022-01-15', title: 'Event 2' }, { id: 3, date: '2022-01-20', title: 'Event 3' }, ], }; }, mounted() { this.setCurrentMonth(); this.setDays(); }, methods: { setCurrentMonth() { const date = new Date(); const options = { month: 'long', year: 'numeric' }; this.currentMonth = date.toLocaleDateString('en-US', options); }, setDays() { const date = new Date(); const year = date.getFullYear(); const month = date.getMonth(); const daysInMonth = new Date(year, month + 1, 0).getDate(); this.days = Array.from({ length: daysInMonth }, (_, index) => index + 1); }, previousMonth() { // 实现切换到上一个月的逻辑 }, nextMonth() { // 实现切换到下一个月的逻辑 }, }, }; </script> <style> .calendar { /* 样式 */ } .header { /* 样式 */ } .days { /* 样式 */ } .day { /* 样式 */ } .events { /* 样式 */ } .event { /* 样式 */ } </style> ``` 这个例子中的日历组件包含一个头部,显示当前月份,以及上一个月和下一个月的按钮。接下来是一个天数的区域,以及事件的区域。你可以根据自己的需求来自定义样式。 这个示例中的事件是固定的,你可以根据你的具体需求从后端获取事件数据,并在`events`数组中进行动态渲染。 在`previousMonth`和`nextMonth`方法中,你可以实现切换到上一个月和下一个月的逻辑,例如更新`currentMonth`和`days`数据,以及获取新月份的事件数据。 希望这个示例能帮到你!如果有任何问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值