首页 前端知识 了解Vue中日历插件Fullcalendar

了解Vue中日历插件Fullcalendar

2024-04-29 12:04:03 前端知识 前端哥 712 149 我要收藏

实现效果如下图:

月视图
在这里插入图片描述

在这里插入图片描述
周视图
在这里插入图片描述
日视图
在这里插入图片描述

官方文档地址:Vue Component - Docs | FullCalendar

1、安装与FullCalendar相关的依赖项

npm install --save @fullcalendar/vue @fullcalendar/core @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/list
npm install --save @fullcalendar/interaction
npm install --save @fullcalendar/core @fullcalendar/resource-timeline

2.使用日历的页面需要导入

import FullCalendar from "@fullcalendar/vue";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import listPlugin from "@fullcalendar/list";
import interactionPlugin from "@fullcalendar/interaction";
// import resourceTimelinePlugin from "@fullcalendar/resource-timeline";

完整代码

<template>
  <div>
    <div class="fc-toolbar">
      <div class="fc-left">
        <el-button-group>
          <el-button @click="month"></el-button>
          <el-button @click="week"></el-button>
          <el-button @click="today"> 今天 </el-button>
        </el-button-group>
      </div>
      <div class="fc-center">
        <el-button icon="el-icon-arrow-left" @click="prev"/>
        <p class="title">
          {{ title }}
        </p>
        <el-button icon="el-icon-arrow-right" @click="next" />
      </div>
      <div>
        <el-select v-model="type" style="margin-right: 20px" @change="handleType">
          <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
        <el-button class="search" style="margin-right: 20px" type="button" @click="addEvent">
          新增
        </el-button>
        <el-button class="search" type="button" @click="search">
          查询
        </el-button>
      </div>
    </div>
    <el-dialog title="添加日程" :visible.sync="dialogFormVisible" width="600px">
      <el-form :model="form">
        <el-form-item label="事件">
          <el-input v-model="form.content" autocomplete="off" placeholder="请输入事件"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="navConfirm">确 定</el-button>
      </div>
    </el-dialog>
    <div v-if="showFullcalendar">加载数据中......</div>
    <FullCalendar v-else 
      id="calendar" 
      ref="fullCalendar" 
      class="demo-app-calendar" 
      :options="calendarOptions"
     >
      <template v-slot:eventContent="arg">
        <el-popover placement="top-start" title="标题" width="200" :visible-arrow="false" trigger="click">
          <i class="title">{{ arg.event.title }}</i>
          <el-button @click="more(arg.event)"> 更多 </el-button>
          <div slot="reference" class="popper-content">
            <span>{{ arg.timeText }}</span>
            <i>{{ arg.event.title }}</i>
          </div>
        </el-popover>
      </template>
      <template v-slot:dayCellContent="arg">
        {{ arg.dayNumberText }}
      </template>
      <template v-slot:resourceLabelContent="arg">
        {{ arg.resource.id }}
      </template>
    </FullCalendar>
  </div>
</template>
<script>
	import FullCalendar from "@fullcalendar/vue";
	import dayGridPlugin from "@fullcalendar/daygrid";
	import timeGridPlugin from "@fullcalendar/timegrid";
	import listPlugin from "@fullcalendar/list";
	import interactionPlugin from "@fullcalendar/interaction";
	// import resourceTimelinePlugin from "@fullcalendar/resource-timeline";
	
	let clickCount = 0;
	let prev = ""; // 上一次点击的dom节点
	export default {
	  components: {
	    FullCalendar, // make the <FullCalendar> tag available
	  },
	  data() {
	    return {
	      showFullcalendar: true,
	      title: "",
	      currentView: {},
	      options: [
	        { value: "timeline", label: "resource-timeline" },
	        { value: "dategrid", label: "agenda" },
	      ],
	      type: "dategrid",
	      calendarOptions: {
	        locale: "zh",
	        timeZone: "UTC",
	        plugins: [
	          dayGridPlugin,
	          timeGridPlugin,
	          listPlugin,
	          // resourceTimelinePlugin,
	          interactionPlugin,
	        ],
	        buttonText: {
	          // 设置按钮
	          today: "今天",
	          month: "月",
	          week: "周",
	          dayGrid: "天",
	        },
	        initialView: "dayGridMonth", // 设置默认显示月,可选周、日
	        resourceAreaWidth: 200,
	        contentHeight: 600,
	        slotMinWidth: 70,
	        resourceOrder: "number",
	        editable: true,
	        dayMaxEvents: true, // allow "more" link when too many events
	        eventDurationEditable: true, // 可以调整事件的时间
	        selectable: true, // 日历格子可选择
	        nowIndicator: true, // 现在的时间线显示
	        eventDisplay: "block", // 争对全天的情况下,以块状显示
	        headerToolbar: false, // 隐藏头部的导航栏
	        selectMirror: false,
	        displayEventEnd: true, // like 08:00 - 13:00
	        eventTimeFormat: {
	          // like '14:30:00'
	          hour: "2-digit",
	          minute: "2-digit",
	          meridiem: false,
	          hour12: false, // 设置时间为24小时
	        },
	        events: [],
	        eventColor: "#378006",
	        allDayText: "全天",
	        dateClick: this.handleDateClick, //点击日程事件
	        eventClick: this.handleEventClick,  //点击日历中的某一日程
	        select:this.handleDateSelect, // 监听用户选择的时间段,
	        eventDrop:this.handleEventDrop,  //监听事件被拖动的操作
	        eventResize:this.handleEventResize, //监听事件调整大小的操作
	        resourceAreaHeaderContent: "Rooms",
	        resources: [
	          {
	            id: "111",
	            title: "asas",
	            number: 1,
	          },
	        ],
	        schedulerLicenseKey: "GPL-My-Project-Is-Open-Source",
	        resourceLabelContent(arg) {
	          return {
	            html: `<div>id: ${arg.resource.id}</div><div>title: ${arg.resource.title}</div>`,
	          };
	        },
	        views: {
	          customTimeLineWeek: {
	            type: "resourceTimeline",
	            duration: { weeks: 1 },
	            slotDuration: { days: 1 },
	            buttonText: "Custom Week",
	            slotLabelFormat: {
	              weekday: "long",
	              // month: 'numeric',
	              // day: 'numeric',
	              omitCommas: true,
	            },
	          },
	          customTimeLineMonth: {
	            type: "resourceTimeline",
	            duration: { month: 1 },
	            slotLabelFormat: {
	              // month: 'numeric',
	              day: "numeric",
	              // omitCommas: true,
	            },
	          },
	          customGridWeek: {
	            type: "timeGridWeek",
	            dayHeaderFormat: {
	              weekday: "long",
	            },
	            slotLabelFormat: {
	              // 左侧时间格式
	              hour: "2-digit",
	              minute: "2-digit",
	              meridiem: "lowercase",
	              hour12: false, // false设置时间为24小时
	            },
	          },
	        },
	        // 切换视图调用的方法
	        datesSet() { },
	      },
	      calendarApi: null,
	      monthEvent: [
	        {
	          id: "1",
	          resourceId: "1",
	          title: "待办",
	          start: "2024-01-04 09:00",
	          end: "2024-01-04 18:00",
	          color: "red",
	        },
	        {
	          resourceId: "2",
	          id: "2",
	          title: "待办",
	          start: "2024-01-15",
	          color: "purple",
	        },
	        { title: "待办", start: "2024-01-09" },
	        { title: "待办", start: "2024-01-17" },
	        { title: "待办", start: "2024-01-07" },
	        { title: "待办", start: "2024-01-07", color: "pink" },
	        { title: "待办", start: "2024-01-07" },
	        { title: "待办", start: "2024-01-07" },
	        {
	          id: "3",
	          resourceId: "number_3",
	          title: "待办",
	          start: "20240111",
	          end: "20240113",
	          color: "blue",
	          extendedProps: {
	            description: "测试测试测试测试",
	          },
	        },
	        {
	          id: 4,
	          title: "待办",
	          start: "2024-01-15",
	          extendedProps: {
	            description: "test test test test test",
	          },
	        },
	      ],
	      weekEvent: [
	        {
	          id: "4",
	          resourceId: "4",
	          title: "周待办",
	          start: "2024-01-11",
	          color: "red",
	        },
	        {
	          id: "5",
	          resourceId: "5",
	          title: "待办1",
	          start: "2024-01-04 10:00",
	          end: "2024-01-04 18:00",
	          color: "orange",
	        },
	      ],
	      dayDate:'',
	      dialogFormVisible:false,
	      form:{
	        content:'',
	      },
	      selectInfo:{},
	    };
	  },
	  mounted() {
	    setTimeout(() => {
	      this.showFullcalendar = false;
	      this.$nextTick(() => {
	        this.calendarApi = this.$refs.fullCalendar.getApi();
	        this.title = this.calendarApi.view.title;
	        this.getDtata();
	      });
	    }, 1000);
	  },
	  watch: {
	    // 切换视图显示不同的事件
	    "calendarApi.view.type"(newVal) {
	      this.getDtata();
	    },
	  },
	  methods: {
	    // 监听用户选择的时间段,当用户选择了一段时间后会触发该回调,可以在这里处理创建新的日程。
	    handleDateSelect(selectInfo) {
	      console.log('selectInfo: ', selectInfo);
	      this.selectInfo = selectInfo;
	      this.form.content = '';
	      // 用户选择了一个日期范围时触发
	      this.dialogFormVisible = true;
	    },
	     // 用户拖动移动事件时触发
	    handleEventDrop(dropInfo) {
	      console.log('dropInfo: ', dropInfo);
	      const updatedEvent = { ...dropInfo.event };
	      updatedEvent.start = dropInfo.revertDuration ? dropInfo.oldEvent.start : dropInfo.event.start;
	      updatedEvent.end = dropInfo.event.end;
	
	      // 更新服务器上的事件或者重新排序你的事件数组
	      // 示例:this.updateEventOnServer(updatedEvent);
	
	      // 如果是在内存中维护事件,则更新本地数据
	      const index = this.events.findIndex(e => e.id === updatedEvent.id);
	      if (index !== -1) {
	        this.events.splice(index, 1, updatedEvent);
	      }
	    },
	     // 用户调整事件长度时触发
	    handleEventResize(resizeInfo) {
	      console.log('resizeInfo: ', resizeInfo);
	      const updatedEvent = { ...resizeInfo.event };
	      updatedEvent.end = resizeInfo.event.end;
	
	      // 同样更新服务器或本地数据
	      // 示例:this.updateEventOnServer(updatedEvent);
	
	      const index = this.events.findIndex(e => e.id === updatedEvent.id);
	      if (index !== -1) {
	        this.events.splice(index, 1, updatedEvent);
	      }
	    },
	    getDtata() {
	      setTimeout(() => {
	        this.calendarOptions.events =
	          this.calendarApi.view.type === "dayGridMonth"
	            ? this.monthEvent
	            : this.weekEvent;
	      }, 200);
	    },
	    // 点击更多
	    more(e) { 
	      console.log('more ', e)
	    },
	    //确认弹框按钮
	    navConfirm(){
	      this.dialogFormVisible = false;
	      if (this.form.content) {
	        this.calendarOptions.events.push({
	          title: this.form.content,
	          start: this.selectInfo.startStr,
	          end: this.selectInfo.endStr,
	        });
	        // 更新日历视图以显示新添加的事件
	        this.$refs.fullCalendar.getApi().addEvent({  //等同于 this.calendarApi.addEvent
	          title: this.form.content,
	          start: this.selectInfo.startStr,
	          end: this.selectInfo.endStr,
	        });
	      }
	    },
	    // 增加事件
	    addEvent() {
	      this.form.content = '';
	      this.dialogFormVisible = true;
	      // this.monthEvent
	    },
	    //点击日历中的某一日程
	    handleEventClick(clickInfo) {
	      console.log('clickInfo:', clickInfo);
	      // 用户点击事件时触发,用于编辑或删除事件
	      const event = clickInfo.event;
	      console.log('Clicked on:', event.title);
	      // 这里可以弹出模态框进行编辑或调用删除函数等操作
	    },
	    // 单击事件(日历中的某一天)
	    handleDateClick(e) {
	      this.dayDate = e.dateStr;
	      if (e.dateStr !== prev) {
	        clickCount = 0;
	      }
	      clickCount += 1;
	      prev = e.dateStr;
	      setTimeout(() => {
	        if (clickCount === 2) {
	          console.log("db click");
	        } else if (clickCount === 1) {
	          console.log("one click");
	        }
	        clickCount = 0;
	      }, 300);
	    },
	    // 切换
	    prev() {
	      this.calendarApi.prev();
	      this.title = this.calendarApi.view.title;
	    },
	    next() {
	      this.calendarApi.next();
	      this.title = this.calendarApi.view.title;
	    },
	    // 今天
	    today(date, jsEvent, view) {
	      // if (this.type === "timeline") {
	      //   this.calendarApi.changeView("customTimeLineWeek");
	      // } else {
	      //   this.calendarApi.changeView("customGridWeek");
	      // }
	      this.calendarApi.today();
	      this.title = this.calendarApi.view.title;
	
	      this.calendarApi.changeView("timeGridDay");
	      // this.calendarApi.today();
	      // this.title = this.calendarApi.view.title;
	    },
	    // 月
	    month() {
	      if (this.type === "timeline") {
	        this.calendarApi.changeView("customTimeLineMonth");
	      } else {
	        this.calendarApi.changeView("dayGridMonth");
	      }
	      this.calendarApi.today();
	      this.title = this.calendarApi.view.title;
	    },
	    // 周
	    week() {
	      if (this.type === "timeline") {
	        this.calendarApi.changeView("customTimeLineWeek");
	      } else {
	        this.calendarApi.changeView("customGridWeek");
	      }
	      this.calendarApi.today();
	      this.title = this.calendarApi.view.title;
	    },
	    // 天
	    day() {
	      this.calendarApi.today();
	      this.title = this.calendarApi.view.title;
	    },
	    // 查询
	    search() {
	      this.calendarApi.changeView("dayGrid", {
	        start: "2022-07-07",
	        end: "2022-07-09",
	      });
	    },
	    // 选择时间线、日程
	    handleType() {
	      if (this.type === "timeline") {
	        this.calendarApi.changeView("customTimeLineMonth");
	        this.calendarOptions.slotLabelFormat = null;
	      } else {
	        this.calendarApi.changeView("dayGridMonth");
	      }
	    },
	  },
	};
</script>
<style scoped>
	.demo-app {
	  display: flex;
	  min-height: 100%;
	  font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
	  font-size: 14px;
	}
	.demo-app-sidebar {
	  width: 300px;
	  line-height: 1.5;
	  background: #eaf9ff;
	  border-right: 1px solid #d3e2e8;
	}
	.demo-app-sidebar-section {
	  padding: 2em;
	}
	.demo-app-main {
	  flex-grow: 1;
	  padding: 3em;
	}
	.fc {
	  /* the calendar root */
	  max-width: 1100px;
	  margin: 0 auto;
	}
	.fc-toolbar {
	  width: 100%;
	  margin: 30px auto;
	  display: flex;
	  flex: 1;
	  justify-content: space-around;
	  align-content: center;
	}
	.fc-center {
	  /* height: 40px; */
	  display: flex;
	  align-content: center;
	}
	.fc-center .title {
	  font-size: 16px;
	  padding: 0 15px;
	  font-weight: 700;
	  /* height: 40px; */
	  /* line-height: 40px; */
	}
</style>

转载请注明出处或者链接地址:https://www.qianduange.cn//article/6472.html
标签
评论
发布的文章

什么是JSON 为什么使用它

2024-05-07 13:05:36

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!