vue-cli中简洁版日历节假日设置功能

在这里插入图片描述图2

效果图和数据结构如上两图所示,简单总结一下需求
1.后台会将本年度的节假日数据提前录入,在页面初始化时,请求回的列表就是上图图2所示,并渲染到页面,holidayName为1,工作日,0为节假日
2.点击某天,可以设置节假日或工作日
3.设置节假日或工作日时,备注为非必填输入项,展现在日期下面的文字就是holidayName

父组件

view/holiday/index.vue

<template>
  <div class="container">
    <div class="buttons">
      <el-button class="holidayButton" type="primary" @click="submitHoliday"
        >设置节假日</el-button
      >
      <el-button class="holidayButton" type="primary" @click="submitWorkDay"
        >设置工作日</el-button
      >
    </div>
    <full-calendar
      firstDay="1"
      lang="zh"
      :events="holidayList"
      @eventClick="eventClick"
      @changeMonth="changeDate"
    >
    </full-calendar>
  </div>
</template> 
<script>
import FullCalendar from "@/components/vue-fullcalendar/fullCalendar";
import {
    
     mapState, mapGetters } from "vuex";
import {
    
     listHoliday, getHoliday, updateHoliday } from "@/api/upms/holiday";
export default {
    
    
  components: {
    
    
    FullCalendar,
  },
  data() {
    
    
    let self = this;
    return {
    
    
      holidayList: [],
      events: [],
      selectedDay: "",
      holidayStatus: "",
      selectedYear: new Date().getFullYear(),
    };
  },
  created() {
    
    
    this.getList(this.selectedYear);
  },
  watch: {
    
    
    selectedYear: function (newVal, oldVal) {
    
    
      if (newVal != oldVal) {
    
    
        this.getList(newVal);
      }
    },
  },
  computed: {
    
    
    ...mapState({
    
    
      useFuncList: (state) => state.useFunction.useFuncList,
    }),
    ...mapGetters(["emplId"]),
  },
  methods: {
    
    
    getList(year) {
    
    
      listHoliday(year).then((response) => {
    
    
        console.log(response);
        this.holidayList = response.data;
      });
    },
    eventClick(date, event, jsEvent, pos) {
    
    
      this.selectedDay = this.parseTime(date, "{y}-{m}-{d}");
    },
    changeDate(start, end, currentStart, currentDate) {
    
    
      this.selectedYear = this.parseTime(currentDate, "{y}");
    },
    submitHoliday() {
    
    
      let param = {
    
    };
      param.holidayDate = this.selectedDay;
      param.holidayFlag = "0";
      param.changeEmplId = this.emplId;
      console.log(param);
      if (this.selectedDay != "") {
    
    
        this.$prompt(
          "请输入备注",
          "确定设置" + this.selectedDay + "为节假日吗?",
          {
    
    
            confirmButtonText: "确定",
            cancelButtonText: "取消",
          }
        )
          .then(({
     
      value }) => {
    
    
            param.holidayName = value;
            updateHoliday(param).then((res) => {
    
    
              this.$message({
    
     message: "设置成功", type: "success" });
              this.getList(this.selectedYear);
            });
          })
          .catch(() => {
    
    
            this.$message({
    
    
              type: "info",
              message: "取消设置",
            });
          });
      } else {
    
    
        this.$message({
    
     message: "请选择日期", type: "error" });
      }
    },
    submitWorkDay() {
    
    
      let param = {
    
    };
      param.holidayDate = this.selectedDay;
      param.holidayFlag = "1";
      param.changeEmplId = this.emplId;
      if (this.selectedDay != "") {
    
    
        this.$prompt(
          "请输入备注",
          "确定设置" + this.selectedDay + "为工作日吗?",
          {
    
    
            confirmButtonText: "确定",
            cancelButtonText: "取消",
          }
        )
          .then(({
     
      value }) => {
    
    
            param.holidayName = value;
            updateHoliday(param).then((res) => {
    
    
              this.$message({
    
     message: "设置成功", type: "success" });
              this.getList(this.selectedYear);
            });
          })
          .catch(() => {
    
    
            this.$message({
    
    
              type: "info",
              message: "取消设置",
            });
          });
      } else {
    
    
        this.$message({
    
     message: "请选择日期", type: "error" });
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.container {
    
    
  padding-top: 30px;
  margin: 0 auto;
  background: #fff;
  .buttons {
    
    
    margin-left: 50px;
  }
}
</style>

子组件(日历组件)目录结构
在这里插入图片描述
components/vue-fullcalendar/fullCalendar.vue

//components/vue-fullcalendar/fullCalendar.vue
<template>
  <div class="comp-full-calendar">
    <!-- header pick month -->
    <fc-header :current-date="currentDate" 
      :title-format="titleFormat"
      :first-day="firstDay"
      :month-names="monthNames"
      @change="emitChangeMonth">

      <div slot="header-left">
        <slot name="fc-header-left">
        </slot>
      </div>

      <div slot="header-right">
        <slot name="fc-header-right">
        </slot>
      </div>
    </fc-header>
    <fc-body :current-date="currentDate" :events="events" :month-names="monthNames" 
      :week-names="weekNames" :first-day="firstDay"
      @eventclick="emitEventClick" @dayclick="emitDayClick"
      @moreclick="emitMoreClick">
      <div slot="body-card">
        <slot name="fc-body-card">
        </slot>
      </div>
    </fc-body>
  </div>
</template>
<script type="text/babel">
  import langSets from './dataMap/langSets'
  import header from './components/header.vue'
  import body from './components/body.vue' 
  export default {
    
    
    props : {
    
    
      events : {
    
     // events will be displayed on calendar
        type : Array,
        default :()=> []
      },
      lang : {
    
    
        type : String,
        default : 'en'
      },
      firstDay : {
    
    
        type : Number | String,
        validator (val) {
    
    
          let res = parseInt(val)
          return res >= 0 && res <= 6
        },
        default : 0
      },
      titleFormat : {
    
    
        type : String,
        default () {
    
    
          return langSets[this.lang].titleFormat
        }
      },
      monthNames : {
    
    
        type : Array,
        default () {
    
    
          return langSets[this.lang].monthNames
        } 
      },
      weekNames : {
    
    
        type : Array,
        default () {
    
    
          let arr = langSets[this.lang].weekNames
          return arr.slice(this.firstDay).concat(arr.slice(0, this.firstDay))
        }
      }
    },
    data () {
    
    
      return {
    
    
        currentDate : new Date()
      }
    },
    methods : {
    
    
      emitChangeMonth (start, end, currentStart, current) {
    
    
        this.currentDate = current
        this.$emit('changeMonth', start, end, currentStart, current)
      },
      emitEventClick (date, event, jsEvent, pos) {
    
    
        // console.log(date,event)
        this.$emit('eventClick', date, event, jsEvent, pos)
      },
      emitDayClick (day, jsEvent) {
    
    
        this.$emit('dayClick', day, jsEvent)
      },
      emitMoreClick (day, events, jsEvent) {
    
    
        this.$emit('moreClick', day, events, jsEvent)
      }
    },
    components : {
    
    
      'fc-body'   : body,
      'fc-header' : header
    }
  }
  
</script>
<style lang="scss">
  .comp-full-calendar{
    
    
    background: #fff;
    width: 100%;
    padding-left: 50px;
    padding-right: 50px;
    ul,p{
    
    
      margin:0;
      padding:0;
      font-size: 14px;
    }
  }
</style>

components/vue-fullcalendar/index.js

//components/vue-fullcalendar/index.js
import vueFullcalendar from './fullCalendar'

const fc = vueFullcalendar

module.exports = fc

components/vue-fullcalendar/dataMap/langSets.js

//components/vue-fullcalendar/dataMap/langSets.js
export default {
    
    
  en : {
    
    
    weekNames   : ['Sun', 'Mon','Tue','Wed','Thu','Fri','Sat'],
    monthNames  : ['January','February','March','April','May','June','July','August','September','October','November','December'],
    titleFormat : 'MMMM yyyy'
  },
  zh : {
    
    
    weekNames   : ['周日', '周一','周二','周三','周四','周五','周六'],
    monthNames  : ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
    titleFormat : 'yyyy年MM月'
  },
  fr : {
    
    
    weekNames   : ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
    monthNames  : ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
    titleFormat : 'MMMM yyyy'
  }
}

components/vue-fullcalendar/components/body.vue
样式的修改,数据的传递处理, 主要集中在这个组件中

//components/vue-fullcalendar/components/body.vue
<template>
  <div class="full-calendar-body">
    <div class="weeks">
      <strong class="week" v-for="(week, index) in weekNames" :key="index">{
    
    {
    
    
        week
      }}</strong>
    </div>
    <div class="dates" ref="dates">
      <!-- absolute so we can make dynamic td -->
      <div class="dates-events">
        <div
          class="events-week"
          v-for="(week, index) in currentDates"
          :key="index"
        >
          <div
            class="events-day"
            v-for="(day, index) in week"
            :key="index"
            track-by="$index"
            :class="{
    
    
              today: day.isToday,
              'not-cur-month': !day.isCurMonth,
              eventBg: day.events.length > 0,
              clickDay: day.date === selectedDay,
            }"
            @click.stop="eventClick(day.date, day.events, $event)"
          >
            <div class="event-box">
              <p
                class="event-item"
                v-for="(event, index) in day.events"
                :key="index"
                v-show="event.cellIndex <= eventLimit"
                :class="[
                  classNames(event.cssClass),
                  {
    
    
                    'is-start': isStart(event.start, day.date),
                    'is-end': isEnd(event.end, day.date),
                    'is-opacity': !event.isShow,
                    'is-work':event.holidayFlag/1==1
                  },
                ]"
              >
                {
    
    {
    
     isBegin(event, day.date, day.weekDay) }}

                <span v-if="event.holidayName">{
    
    {
    
    event.holidayName?event.holidayName:''}}</span>
              </p>
              <p
                v-if="day.events.length > eventLimit"
                class="more-link"
                @click.stop="selectThisDay(day, $event)"
              >
                +
                {
    
    {
    
    
                  day.events[day.events.length - 1].cellIndex - eventLimit
                }}
                more
              </p>

            </div>
            <p class="day-number" :class="{ eventDay: day.events.length > 0,'iswork':day.events.length > 0&&day.events[0].holidayFlag/1==1 }" >
              {
    
    {
    
     day.monthDay }}
              
            </p>
            
          </div>
        </div>
      </div>

      <!-- <div class="dates-bg">
        <div class="week-row" v-for="week in currentDates">
          <div class="day-cell" v-for="day in week"
            :class="{
    
    'today' : day.isToday,
              'not-cur-month' : !day.isCurMonth}">
            <p v-if="day.events.length == 0" class="day-number">{
    
    {
    
    day.monthDay}}</p>
          </div>
        </div>
      </div> -->

      <!-- full events when click show more -->
      <div
        class="more-events"
        v-show="showMore"
        :style="{ left: morePos.left + 'px', top: morePos.top + 'px' }"
      >
        <div class="more-header">
          <span class="title">{
    
    {
    
     moreTitle(selectDay.date) }}</span>
          <span class="close" @click.stop="showMore = false">x</span>
        </div>
        <div class="more-body">
          <ul class="body-list">
            <li
              v-for="(event, index) in selectDay.events"
              :key="index"
              :id='index'
              v-show="event.isShow"
              class="body-item"
              @click="eventClick(event, $event)"
            >
              {
    
    {
    
     eventTitle}} 
            </li>
          </ul>
        </div>
      </div>

      <slot name="body-card"> </slot>
    </div>
  </div>
</template>
<script type="text/babel">
import dateFunc from "./dateFunc";
export default {
    
    
  props: {
    
    
    currentDate: {
    
    },
    events: {
    
    
      type: Array,
    },
    weekNames: {
    
    
      type: Array,
      default: [],
    },
    monthNames: {
    
    },
    firstDay: {
    
    },
  },
  watch: {
    
    },
  created() {
    
    

      // setTimeout(() => {
    
    
      //   }, 1000)
        this.handleEvents()
    // this.events = events
  },
  data() {
    
    
    return {
    
    
      // weekNames : DAY_NAMES,
      weekMask: [1, 2, 3, 4, 5, 6, 7],
      // events : [],
      isLismit: true,
      eventLimit: 1,
      showMore: false,
      morePos: {
    
    
        top: 0,
        left: 0,
      },
      selectDay: {
    
    },
      eventTitle: "休",
      selectedDay: "",
    };
  },
  watch: {
    
    
    weekNames(val) {
    
    
      console.log("watch weekNames", val);
    },
    events(newVal, oldVal) {
    
    
      if (newVal.length > 0) {
    
    
        this.handleEvents()
      }
    },
  },
  computed: {
    
    
    currentDates() {
    
    
      return this.getCalendar();
    },
  },
  methods: {
    
    
    handleEvents() {
    
    
      this.events.forEach((item, index) => {
    
    
        item._id = item.id || index;
        (item.start = item.holidayDate),
          (item.end = item.start || item.holidayDate);
      });
      // console.log(this.events)
    },
    isBegin(event, date, index) {
    
    
      //  console.log(event)
      let st = new Date(event.start);
      if (index == 0 || st.toDateString() == date.toDateString()) {
    
    
        if(event.holidayFlag/1==0){
    
    
          return this.eventTitle;
        }else if(event.holidayFlag/1==1){
    
    
          return "班"
        }
      }
      return " ";
    },
    moreTitle(date) {
    
    
      let dt = new Date(date);
      return (
        this.weekNames[dt.getDay()] +
        ", " +
        this.monthNames[dt.getMonth()] +
        dt.getDate()
      );
    },
    classNames(cssClass) {
    
    
      // console.log(cssClass)
      if (!cssClass) return "";
      // string
      if (typeof cssClass == "string") return cssClass;

      // Array
      if (Array.isArray(cssClass)) return cssClass.join(" ");

      // else
      return "";
    },
    getCalendar() {
    
    
      // calculate 2d-array of each month
      // first day of this month
      let now = new Date(); // today
      let current = new Date(this.currentDate);

      let startDate = dateFunc.getStartDate(current); // 1st day of this month

      let curWeekDay = startDate.getDay();
      // begin date of this table may be some day of last month
      let diff = parseInt(this.firstDay) - curWeekDay;
      diff = diff > 0 ? diff - 7 : diff;

      startDate.setDate(startDate.getDate() + diff);
      let calendar = [];

      for (let perWeek = 0; perWeek < 6; perWeek++) {
    
    
        let week = [];

        for (let perDay = 0; perDay < 7; perDay++) {
    
    
          week.push({
    
    
            monthDay: startDate.getDate(),
            isToday: now.toDateString() == startDate.toDateString(),
            isCurMonth: startDate.getMonth() == current.getMonth(),
            weekDay: perDay,
            date: new Date(startDate),
            events: this.slotEvents(startDate),
          });
          startDate.setDate(startDate.getDate() + 1);
          // if (startDate.toDateString() == endDate.toDateString()) {
    
    
          //   isFinal = true
          //   break
          // }
        }

        calendar.push(week);
      }
      return calendar;
    },
    slotEvents(date) {
    
    
      // find all events start from this date
      let cellIndexArr = [];
      let thisDayEvents = this.events.filter((day) => {
    
    
        let dt = new Date(day.start);
        let st = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
        let ed = day.end ? new Date(day.end) : st;
        // console.log('slotEvt', st, ed, date)
        return date >= st && date <= ed;
      });

      // sort by duration
      thisDayEvents.sort((a, b) => {
    
    
        if (!a.cellIndex) return 1;
        if (!b.cellIndex) return -1;
        return a.cellIndex - b.cellIndex;
      });

      // mark cellIndex and place holder
      for (let i = 0; i < thisDayEvents.length; i++) {
    
    
        thisDayEvents[i].cellIndex = thisDayEvents[i].cellIndex || i + 1;
        thisDayEvents[i].isShow = true;
        if (thisDayEvents[i].cellIndex == i + 1 || i > 2) continue;
        thisDayEvents.splice(i, 0, {
    
    
          title: "holder",
          cellIndex: i + 1,
          start: dateFunc.format(date, "yyyy-MM-dd"),
          end: dateFunc.format(date, "yyyy-MM-dd"),
          isShow: false,
        });
      }

      return thisDayEvents;
    },
    isStart(eventDate, date) {
    
    
      let st = new Date(eventDate);
      return st.toDateString() == date.toDateString();
    },
    isEnd(eventDate, date) {
    
    
      let ed = new Date(eventDate);
      return ed.toDateString() == date.toDateString();
    },
    selectThisDay(day, jsEvent) {
    
    
      this.selectDay = day;
      this.showMore = true;
      this.morePos = this.computePos(event.target);
      this.morePos.top -= 100;
      let events = day.events.filter((item) => {
    
    
        return item.isShow == true;
      });
      this.$emit("moreclick", day.date, events, jsEvent);
    },
    computePos(target) {
    
    
      let eventRect = target.getBoundingClientRect();
      let pageRect = this.$refs.dates.getBoundingClientRect();
      return {
    
    
        left: eventRect.left - pageRect.left,
        top: eventRect.top + eventRect.height - pageRect.top,
      };
    },
    dayClick(day, event) {
    
    
      this.$emit("dayclick", day, event);
    },
    eventClick(date, event, jsEvent) {
    
    
      // console.log(date,event)
      // if (!event.isShow) {
    
    
      //   return
      // }
      // jsEvent.target.classList.add("clickDay");
      this.selectedDay = date;
      jsEvent.stopPropagation();
      let pos = this.computePos(jsEvent.target);
      this.$emit("eventclick", date, event, jsEvent, pos);
    },
  },
};
</script>
<style lang="scss">
.full-calendar-body {
    
    
  margin-top: 20px;
  .weeks {
    
    
    height: 30px;
    line-height: 30px;
    display: flex;
    border-top: 1px solid #dfe6ec;
    border-bottom: 1px solid #dfe6ec;
    border-left: 1px solid #dfe6ec;
    .week {
    
    
      flex: 1;
      text-align: center;
      border-right: 1px solid #dfe6ec;
    }
  }
  .dates {
    
    
    position: relative;
    .week-row {
    
    
      // width: 100%;
      // position:absolute;
      border-left: 1px solid #dfe6ec;
      display: flex;
      .day-cell {
    
    
        flex: 1;
        min-height: 90px;
        padding: 4px;
        border-right: 1px solid #dfe6ec;
        border-bottom: 1px solid #dfe6ec;
        .day-number {
    
    
          text-align: center;
          font-size: 20px;
          font-weight: bold;
          height: 100%;
          display: flex;
          justify-content: center;
          align-items: center;
        }
        &.today {
    
    
          background-color: #fcf8e3;
        }
        &.not-cur-month {
    
    
          .day-number {
    
    
            color: rgba(0, 0, 0, 0.24);
          }
        }
      }
    }
    .dates-events {
    
    
      // position:absolute;
      position: relative;
      top: 0;
      left: 0;
      z-index: 1;
      width: 100%;
      border-left: 1px solid #dfe6ec;
      .events-week {
    
    
        display: flex;
        border-bottom: 1px solid #dfe6ec;
        .events-day:hover {
    
    
          background-color: rgba(102, 153, 255, 0.1);
        }
        .events-day {
    
    
          cursor: pointer;
          flex: 1;
          min-height: 90px;
          overflow: hidden;
          text-overflow: ellipsis;
          border-right: 1px solid #dfe6ec;
          position: relative;
          &.eventBg {
    
    
            background-color: #f5f5f5;
          }
          &.clickDay {
    
    
            background-color: rgba(102, 153, 255, 0.2);
          }
          .day-number {
    
    
            text-align: center;
            font-size: 20px;
            font-weight: bold;
            height: 100%;
            margin-top: -30px;
            display: flex;
            justify-content: center;
            align-items: center;

            &.eventDay {
    
    
              color:#e02d2d;
            }
            &.iswork{
    
    
              color:#000;
            }
          }
          &.today {
    
    
            background-color: #fcf8e3;
          }
          &.not-cur-month {
    
    
            pointer-events: none;
            .day-number {
    
    
              color: rgba(0, 0, 0, 0.24);
            }
          }
          .event-box {
    
    
            height: 30px;
           
            .event-item {
    
    
              cursor: pointer;
              text-align: center;
              font-size: 18px;
              font-weight: bold;
              background-color: #f43;
              margin-bottom: 2px;
              color: #fff;
              // padding: 2px 5px;
              height: 100%;
              line-height: 30px;
              width:30px;
            
              white-space: nowrap;
              overflow: hidden;
              text-overflow: ellipsis;
             
              &.is-start {
    
    
                margin-left: 4px;
                // border-top-left-radius:4px;
                // border-bottom-left-radius:4px;
              }
              &.is-end {
    
    
                margin-right: 4px;
                // border-top-right-radius:4px;
                // border-bottom-right-radius:4px;
              }
              &.is-opacity {
    
    
                opacity: 0;
              }
              &.is-work{
    
    
                 background-color: #969799;
                 span{
    
    
                   color:#999;
                 }
              }
              span{
    
    
                position: absolute;
                bottom: 5px;
                left: 0;
                right: 0;
                margin: auto;
                color:#e02d2d;
                font-size: 14px;
              }
            }
            .more-link {
    
    
              cursor: pointer;
              // text-align: right;
              padding-left: 8px;
              padding-right: 2px;
              color: rgba(0, 0, 0, 0.38);
              font-size: 14px;
            }
          }
        }
      }
    }
    .more-events {
    
    
      // position:absolute;
      position: relative;
      width: 150px;
      z-index: 2;
      border: 1px solid #eee;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
      .more-header {
    
    
        background-color: #eee;
        padding: 5px;
        display: flex;
        align-items: center;
        font-size: 14px;
        .title {
    
    
          flex: 1;
        }
        .close {
    
    
          margin-right: 2px;
          cursor: pointer;
          font-size: 16px;
        }
      }
      .more-body {
    
    
        height: 140px;
        overflow: hidden;
        .body-list {
    
    
          height: 120px;
          padding: 5px;
          overflow: auto;
          background-color: #fff;
          .body-item {
    
    
            cursor: pointer;
            font-size: 12px;
            background-color: #c7e6fd;
            margin-bottom: 2px;
            color: rgba(0, 0, 0, 0.87);
            padding: 0 0 0 4px;
            height: 18px;
            line-height: 18px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
        }
      }
    }
  }
}
</style>

components/vue-fullcalendar/components/header.vue

//components/vue-fullcalendar/components/header.vue
<template>
  <div class="full-calendar-header">
    <div class="header-left">
      <slot name="header-left">
      </slot>
    </div>
    <div class="header-center">
      <!-- <span class="prev-month" @click.stop="goPrev">{
    
    {
    
    leftArrow}}</span>
      <span class="title">{
    
    {
    
    title}}</span>
      <span class="next-month" @click.stop="goNext">{
    
    {
    
    rightArrow}}</span> -->
      <el-date-picker
          v-model="nowMonth"
          type="month"
          placeholder="选择月"
          value-format="yyyy-MM"
          :clearable = "false"
          @change="changeMonthDay"
          style="font-size: 16px;font-weight: bold;">
      </el-date-picker>
      <el-button class="to-today" type="primary" plain @click="toDate">本月</el-button>
    </div>
    <div class="header-right">
      <slot name="header-right">
      </slot>
    </div>
  </div>
</template>
<script type="text/babel">
  import dateFunc from './dateFunc'

  export default {
    
    
    created () {
    
    
      this.dispatchEvent()
    },
    props : {
    
    
      currentDate : {
    
    },
      titleFormat : {
    
    },
      firstDay    : {
    
    },
      monthNames  : {
    
    }
    },
    data () {
    
    
      return {
    
    
        title      : '',
        leftArrow  : '<',
        rightArrow : '>',
        headDate : new Date(),
        nowMonth : dateFunc.format(new Date(), 'yyyy-MM')
      }
    },
    watch : {
    
    
      currentDate (val) {
    
    
        if (!val) return
        this.headDate = val
        // this.headDate = JSON.parse(JSON.stringify(val))
      }
    },
    methods : {
    
    
      toDate() {
    
    
        this.headDate = new Date()
        this.nowMonth = new Date()
        this.dispatchEvent()
      },
      goPrev () {
    
    
        this.headDate = this.changeMonth(this.headDate, -1)
        this.dispatchEvent()
      },
      goNext () {
    
    
        this.headDate = this.changeMonth(this.headDate, 1)
        this.dispatchEvent()
      },
      changeMonth (date, num) {
    
    
        let dt = new Date(date)
        return new Date(dt.setMonth(dt.getMonth() + num))
      },
      dispatchEvent() {
    
    
        this.title = dateFunc.format(this.headDate, this.titleFormat, this.monthNames)

        let startDate = dateFunc.getStartDate(this.headDate)
        let curWeekDay = startDate.getDay()

        // 1st day of this monthView
        let diff = parseInt(this.firstDay) - curWeekDay
        if (diff) diff -= 7
        startDate.setDate(startDate.getDate() + diff) 

        // the month view is 6*7
        let endDate = dateFunc.changeDay(startDate, 41)

        // 1st day of current month
        let currentDate = dateFunc.getStartDate(this.headDate)

        this.$emit('change', 
          dateFunc.format(startDate, 'yyyy-MM-dd'),
          dateFunc.format(endDate, 'yyyy-MM-dd'),
          dateFunc.format(currentDate,'yyyy-MM-dd'),
          this.headDate
        )
      },
      changeMonthDay(value) {
    
    
        this.headDate = new Date(value);
        this.dispatchEvent()
      }
    }
  }
</script>
<style lang="scss">
.full-calendar-header{
    
    
  display: flex;
  align-items: center;
  .header-left,.header-right{
    
    
    flex:1;
  }
  .header-center{
    
    
    flex:3;
    text-align:center;
    font-size:18px;
    .to-today{
    
    
      margin-left: 30px;
    }
    .title{
    
    
      margin: 0 10px;
    }
    .prev-month,.next-month{
    
    
      cursor: pointer;
    }
  }
}
</style>

components/vue-fullcalendar/components/dateFunc.js

//components/vue-fullcalendar/components/dateFunc.js
var shortMonth = [
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec'
]
var defMonthNames = [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December'
]

let dateFunc = {
    
    
  getDuration (date) {
    
    
    // how many days of this month
    let dt = new Date(date)
    var month = dt.getMonth()
    dt.setMonth(dt.getMonth() + 1)
    dt.setDate(0);
    return dt.getDate()
  },
  changeDay (date, num) {
    
    
    let dt = new Date(date)
    return new Date(dt.setDate(dt.getDate()+num))
  },
  getStartDate(date) {
    
    
    // return first day of this month
    return new Date(date.getFullYear(), date.getMonth(), 1)
  },
  getEndDate (date) {
    
    
    // get last day of this month
    let dt = new Date(date.getFullYear(),date.getMonth()+1,1) // 1st day of next month
    return new Date(dt.setDate(dt.getDate()-1)) // last day of this month
  },
  format (date, format, monthNames) {
    
    
    monthNames = monthNames || defMonthNames
    if (typeof date === 'string') {
    
    
        date = new Date(date.replace(/-/g, '/'))
    } else {
    
    
        date = new Date(date)
    }

    var map = {
    
    
        'M' : date.getMonth() + 1,
        'd' : date.getDate(),
        'h' : date.getHours(),
        'm' : date.getMinutes(),
        's' : date.getSeconds(),
        'q' : Math.floor((date.getMonth() + 3) / 3),
        'S' : date.getMilliseconds()
    }

    format = format.replace(/([yMdhmsqS])+/g, (all, t) => {
    
    
            var v = map[t]
            if (v !== undefined) {
    
    
                if (all === 'MMMM') {
    
    
                    return monthNames[v - 1]
                }
                if (all === 'MMM') {
    
    
                    return shortMonth[v - 1]
                }
                if (all.length > 1) {
    
    
                    v = '0' + v
                    v = v.substr(v.length - 2)
                }
                return v
            } else if (t === 'y') {
    
    
                return String(date.getFullYear()).substr(4 - all.length)
            }
        return all
    })
    return format
  }
}
export default dateFunc

components/vue-fullcalendar/components/eventCard.vue
其实这里面没东西啦

<template>
</template>
<script type="text/javascript"></script>

补充:有人说没有parseTime的方法,现在补充一下,可以挂在到全局,也可单独写个moudle,随你心意

export function parseTime (time, pattern) {
    
    
  if (arguments.length === 0 || !time) {
    
    
    return null
  }
  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    
    
    date = time
  } else {
    
    
    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
    
    
      time = parseInt(time)
    } else if (typeof time === 'string') {
    
    
      time = time.replace(new RegExp(/-/gm), '/')
    }
    if ((typeof time === 'number') && (time.toString().length === 10)) {
    
    
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    
    
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    
    
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
    
     return ['日', '一', '二', '三', '四', '五', '六'][value] }
    if (result.length > 0 && value < 10) {
    
    
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

猜你喜欢

转载自blog.csdn.net/weixin_41884808/article/details/110433903
今日推荐