vue2项目使用FullCalendar日历组件,实现获取某年的排除节假日及其周末的日期功能

背景

项目需求:需要经过图形界面化获取经过选择某一年的日排除节假日及周末的日期;或则勾选或取消勾选不需要的日期

使用前提条件

安装FullCalendar日历组件,其安装命令如下

npm install --save @fullcalendar/moment
npm install --save @fullcalendar/core
npm install --save @fullcalendar/vue 
npm install --save @fullcalendar/daygrid
npm install --save @fullcalendar/multimonth

template里的代码

<template>
  <div class="main">
    <h1>
        fullcalendar年日历例子
    </h1>
    <FullCalendar ref="funllCalendarRef" 	:options="calendarOptions" >
    </FullCalendar>
    <div class="button">
      <el-button type="primary" @click="getSelectHandle">获取已经选择的数据</el-button>
    </div>
  </div>
</template>

script里的代码

说明:holidayData节假日的数据目前写死的一个js文件返回的常量,根据具体接口请求数据并根据数据显示不同的样式

import FullCalendar from "@fullcalendar/vue";
import zhcn from "@fullcalendar/core/locales/zh-cn"; //中文
import momentPlugin from "@fullcalendar/moment"; //时间格式化,但是要先npm i moment
import multiMonthPlugin from '@fullcalendar/multimonth'
import moment from 'moment'
import { holidayData } from '@/data/holidayData.js'
export default {
  components: {
    FullCalendar,
  },
  data() {
    return {
      myCalendar: null,
      calendarOptions: {
        plugins: [multiMonthPlugin],
        initialView: 'multiMonthYear',
        locale: zhcn, //中文包
        customButtons: { 
          // 全部复选框选择
          selectAllButton: { text: "排除周六日节假日全选", click: this.handleSelectAllButton, style: '{ background-color: #409EFF }' },
          // 取消全部复选框选择
          cancelSelectAllButton: { text: "取消全选", click: this.handleCancelSelectAllButton, style: '{ background-color: #E6A23C }' },
          prevYearCustom: {
            text: '上一年',
            click: () => {
              this.prevYearHandl();
            }
          },
          nextYearCustom: {
            text: '下一年',
            click: () => {
              this.nextYearHandl();
            }
          },
        }, //自定义按钮
        // buttonText: {},
        headerToolbar: {
          left: 'selectAllButton cancelSelectAllButton',
          center: 'title',
          // right: 'multiMonthYear,dayGridMonth,timeGridWeek'
          // right: 'today prev next',
          // right: 'today prevYear nextYear',
          right: 'today prevYearCustom nextYearCustom',
        },
        events: [
          { title: 'Event 1', date: '2024-06-01', id: '1', completed: false },
          { title: 'Event 2', date: '2024-06-02', id: '2', completed: true }
          // more events...
        ],
        eventContent: this.renderEventContent.bind(this),
        // 今日上一年视图
        prevYear: this.prevYearHandl,
        // 今日下一年视图
        nextYear: this.nextYearHandl,
        // eventClick: this.handleDelete, //事件点击
      },
      // year: 2024, // 你可以根据需要更改这个年份  
      year: moment().format('YYYY'), // 你可以根据需要更改这个年份  
      // 全年的日期
      dates: [],
    };
  },
  mounted() {
    this.myCalendar = this.$refs.funllCalendarRef.getApi(); //获取日历Api
    window.handleCheckboxChange = this.handleCheckboxChange.bind(this);
    // this.handleGetDate()
    this.generateDatesForYear(this.year)
    this.getEventList(this.dates);
    let calendarApi = this.$refs.funllCalendarRef.getApi()
  },
  methods: {
    // 获取全年日期
    generateDatesForYear(year) {  
      const startOfYear = moment(`${year}-01-01`, 'YYYY-MM-DD');  
      const endOfYear = moment(`${year}-12-31`, 'YYYY-MM-DD').endOf('day');  
      // 先清空在加入
      this.dates = []
      let currentDate = startOfYear.clone();  
      while (currentDate.isBefore(endOfYear)) {  
        this.dates.push(currentDate.clone().format('YYYY-MM-DD')); // 使用clone()来避免在循环中修改原始moment对象  
        currentDate.add(1, 'days');  
      }  
      return this.dates
    },
    handleGetDate(){
      let num= Math.ceil(365/7)*7
      let start=new Date(moment().format('yyyy-01-01')).getDay()
      let YYYY = this.year
      let dateArr=[],time=moment().format('yyyy-01-01')
      for(let i=0;i<num;i++){
        if(i < start || time > moment( YYYY+ '-12').endOf('month').format('yyyy-MM-DD')){
                dateArr.push(0)
        }
        else{ dateArr.push(time);time=moment(time).add(1,'days').format('yyyy-MM-DD') } 
      console.log('dateArr', dateArr)
    },
    // 获取节假日名
    getHoliday(date) {
      let holidayName = ''
      holidayData.forEach(item => {
        // 找出节假日并且不是补班的
        // if(date == item.HoDate && !item.HoName.includes('补班')) {
        // 找出节假日和补班的
        if(date == item.HoDate) {
          holidayName = item.HoName
        }
      })
      return holidayName
    },
    // 渲染全年的复选框 参数:dates:全年日期
    getEventList(dates) {
      // this.calendarOptions.events = []
      this.calendarOptions.events = dates.map((item, index) => {
        return {
          title: this.getHoliday(item),
          date: item, id: index, completed: false
        }
      })

      
    },
    // 新增日程
    handleAdd() {
      console.log("新建事件");
      var dateStr = prompt("输入日期YYYY-MM-DD格式");
      var date = new Date(dateStr + "T00:00:00");
      if (!isNaN(date.valueOf())) {
        this.myCalendar.addEvent({
          title: "新增日程",
          start: date,
          allDay: true,
        });
      } else {
        alert("Invalid date.");
      }
    },
    // 点击日程删除
    handleDelete(info) {
      console.log('info', info)
      let event = this.myCalendar.getEventById(info.event.id);
      event.remove();
    },
    // 渲染事件内容
    renderEventContent(eventInfo) {
      const event = eventInfo.event;
      const checked = event.extendedProps.completed ? 'checked' : '';
      const id = event.id;

      return {
        html: 
        // 节假日标不同的颜色
        !event.title ?
        `
          <div class="event-box">
            <input type="checkbox" id="checkbox-${id}" ${checked} οnchange="handleCheckboxChange(event, '${id}')" />
          </div>
        `
        : 
        event.title.includes('补班') ? 
        `
          <div class="event-box">
            <input type="checkbox" id="checkbox-${id}" ${checked} οnchange="handleCheckboxChange(event, '${id}')" />
            <label class="event-title-buban" for="checkbox-${id}">${event.title}</label>
          </div>
        `
        :
        `
          <div class="event-box">
            <input type="checkbox" id="checkbox-${id}" ${checked} οnchange="handleCheckboxChange(event, '${id}')" />
            <label class="event-title" for="checkbox-${id}">${event.title}</label>
          </div>
        `
      };
    },
    // 选择复选框
    handleCheckboxChange(event, eventId) {
      const checked = event.target.checked;
      const calendarApi = this.$refs.funllCalendarRef.getApi();
      const calendarEvent = calendarApi.getEventById(eventId);

      if (calendarEvent) {
        calendarEvent.setExtendedProp('completed', checked);
      }
      this.$refs.funllCalendarRef.options.events.forEach(item => {
        if(item.id == eventId) {
          item.completed = event.target.checked
        }
      })
      console.log('this.$refs.funllCalendarRef', this.$refs.funllCalendarRef.options.events)
    },
    // 今日上一年视图
    prevYearHandl() {
      console.log('上一年')
      console.log('this.$refs.funllCalendarRef', this.$refs.funllCalendarRef)
      // this.$refs.funllCalendarRef.prevYear();
      this.myCalendar.prevYear()
      console.log('获取日期', this.myCalendar.getDate())
      // 获取当前年
      this.year = moment(this.myCalendar.getDate()).format('YYYY')
      // 获取上一年日期
      this.generateDatesForYear(this.year)
      // 移出之前的复选框
      /* this.calendarOptions.events.forEach(item => {
        let event = this.myCalendar.getEventById('checkbox-' + item.id);
        event.remove();
      }) */

      console.log('this.calendarOptions.events', this.calendarOptions.events)

      // 渲染复选框
      this.getEventList(this.dates)
    },
    // 今日下一年视图
    nextYearHandl() {
      console.log('下一年')
      console.log('this.$refs.funllCalendarRef', this.$refs.funllCalendarRef)
      this.myCalendar.nextYear();
      console.log('获取日期', this.myCalendar.getDate())
      // 获取当前年
      this.year = moment(this.myCalendar.getDate()).format('YYYY')
      // 获取下一年日期
      this.generateDatesForYear(this.year)
      // 渲染复选框
      this.getEventList(this.dates)
      this.myCalendar.render()
    },
    // 设置复选框是否勾选
    // 参数:dates:全年日期,completed:是否被选择
    setEventList(dates, completed) {
      this.calendarOptions.events = this.calendarOptions.events.map(item1 => {
        dates.forEach((item2, index) => {
          if(item1.date == item2) {
            item1.completed = completed
          }
        })
        return item1
      })
      console.log('this.calendarOptions.events', this.calendarOptions.events)
    },
    // 排除节假日和周末的日期,周末为补班的不排查
    workdayHandle() {
      // 工作日
      let workdayArr = []
      // 节假日
      let holidayDataArr = []
      // 补班日
      let holidayDataArr1 = []
      holidayData.forEach(item => {
        if(!item.HoName.includes('补班')) {
          holidayDataArr.push(item.HoDate)
        }
        if(item.HoName.includes('补班')) {
          holidayDataArr1.push(item.HoDate)
        }
      })
      this.dates.forEach(item => {
        // 找出没有节假日的日期
        if(!holidayDataArr.includes(item)) {
          workdayArr.push(item)
        }
      })
      console.log('holidayDataArr', holidayDataArr)
      console.log('workdayArr', workdayArr.filter(item => holidayDataArr1.includes(item) || (moment(item).weekday() != 0 && moment(item).weekday() != 6)))
      // 返回不是周六日及是补班日的日期
      return workdayArr.filter(item => holidayDataArr1.includes(item) || (moment(item).weekday() != 0 && moment(item).weekday() != 6))
    },
    // 全部复选框选择
    handleSelectAllButton() {
      console.log('全选')
      console.log('排查节假期和工作日的日期', this.workdayHandle())
      this.setEventList(this.workdayHandle(), true)
    },
    // 取消全部复选框选择
    handleCancelSelectAllButton() {
      console.log('取消全选')
      this.setEventList(this.dates, false)
    },
    // 获取已选择的数据
    getSelectHandle() {
      let selectArr = []
      this.calendarOptions.events.forEach(item => {
        if(item.completed) {
          selectArr.push(item)
        }
      })
      console.log('获取已选择的数据', selectArr)
    }
  },
};
</script>

style样式代码

<style scoped lang="less">
.main {
  width: 700px;
  height: 700px;
  margin: 50px auto;

  .button {
    margin-top: 20px;
    text-align: center;
  }

  .event-box {
    position: relative;
  }

  // 节假日样式
  /deep/.event-title {
    margin-left: 4px;
    color: #EB3333;
  }
  // 补班样式
  /deep/ .event-title-buban {
    margin-left: 4px;
    color: #4E5877;
  }

// 节假日事件标题
// .fc-event-main .event-box
/deep/ label.event-title::before {
  content: "休";
  display: inline-block;
  font-size: 10px;
  position: absolute;
  top: -27px;
  right: 69px;
  width: 20px;
  height: 20px;
  background: rgb(224, 32, 32);
  color: white;
  text-align: center;
  line-height: 20px;
  border-radius: 10px;
}

// 补班事件标题
/deep/ label.event-title-buban::before {
  content: "班";
  display: inline-block;
  font-size: 10px;
  position: absolute;
  top: -27px;
  right: 69px;
  width: 20px;
  height: 20px;
  background: #4E5877;
  color: white;
  text-align: center;
  line-height: 20px;
  border-radius: 10px;
}

// 修改标题背景颜色
/deep/.fc-h-event {
  background-color: transparent;
  border: none;
} 

// 日历表头周六日的字体颜色
  /deep/.fc-multimonth-header >.fc-multimonth-header-table>thead>tr>th:nth-child(6)>.fc-scrollgrid-sync-inner>.fc-col-header-cell-cushion
  {
    color: #EB3333;
  }
  /deep/.fc-multimonth-header >.fc-multimonth-header-table>thead>tr>th:nth-child(7)>.fc-scrollgrid-sync-inner>.fc-col-header-cell-cushion{
    color: #EB3333;
  }

  // 日历内容周六日的字体颜色
  /deep/.fc-multimonth-daygrid >.fc-multimonth-daygrid-table >tbody>tr>td:nth-child(6)>.fc-daygrid-day-frame>.fc-daygrid-day-top>.fc-daygrid-day-number
  {
    color: #EB3333;
  }
  /deep/.fc-multimonth-daygrid >.fc-multimonth-daygrid-table >tbody>tr>td:nth-child(7)>.fc-daygrid-day-frame>.fc-daygrid-day-top>.fc-daygrid-day-number{
    color: #EB3333;
  }

  // 周六日显示不同的颜色
  /deep/.el-calendar-table
    tr.el-calendar-table__row
    td:nth-child(6) {
    color: #EB3333;
    // color: #67C23A;
  }
  /deep/.el-calendar-table
    tr.el-calendar-table__row
    td:nth-child(7) {
    color: #EB3333;
    // color: #67C23A;
  }

  // 把每格设置相对定位
  /deep/.el-calendar-table tr.el-calendar-table__row td {
    position: relative;
  }


}
// 修改日期内容中文字的颜色
/deep/.fc .fc-col-header-cell-cushion,
/deep/.fc .fc-daygrid-day-number {
    color: #2c3e50;
}



</style>

holidayData模拟2024年节假日的数据

// 2024年节假日数据
export const holidayData = [
    {
      "HoDate": "2024-10-12",
      "HoName": "国庆节后补班",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-04-07",
      "HoName": "清明节后补班",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-06-09",
      "HoName": "端午节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-04-04",
      "HoName": "清明节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-04-05",
      "HoName": "清明节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-06-08",
      "HoName": "端午节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-04-06",
      "HoName": "清明节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-04-28",
      "HoName": "劳动节前补班",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-04",
      "HoName": "春节前补班",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-05-11",
      "HoName": "劳动节后补班",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-09-17",
      "HoName": "中秋节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-09-16",
      "HoName": "中秋节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-09-15",
      "HoName": "中秋节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-09-14",
      "HoName": "中秋节前补班",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-10-01",
      "HoName": "国庆节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-18",
      "HoName": "春节后补班",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-17",
      "HoName": "初八",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-16",
      "HoName": "初七",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-11",
      "HoName": "初二",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-05-05",
      "HoName": "劳动节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-10",
      "HoName": "初一",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-05-04",
      "HoName": "劳动节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-15",
      "HoName": "初六",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-05-01",
      "HoName": "劳动节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-09-29",
      "HoName": "国庆节前补班",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-14",
      "HoName": "初五",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-01-01",
      "HoName": "元旦",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-13",
      "HoName": "初四",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-05-03",
      "HoName": "劳动节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-02-12",
      "HoName": "初三",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-05-02",
      "HoName": "劳动节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-10-03",
      "HoName": "国庆节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-10-02",
      "HoName": "国庆节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-10-05",
      "HoName": "国庆节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-06-10",
      "HoName": "端午节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-10-04",
      "HoName": "国庆节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-10-07",
      "HoName": "国庆节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    },
    {
      "HoDate": "2024-10-06",
      "HoName": "国庆节",
      "Years": "2024",
      "FUpdateTime": "2024-06-12 09:43:33"
    }
]

最终样式效果

在这里插入图片描述

参考1
FullCalendar 中文说明文档
FullCalendar官网

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值