在Vue中引入fullcalendar

// 引入步骤
//   1、安装插件
//       yarn引入方式
//         yarn add @fullcalendar/vue @fullcalendar/core @fullcalendar/daygrid @fullcalendar/interaction @fullcalendar/list @fullcalendar/timegrid
//       npm引入方式
//         npm install --save @fullcalendar/vue @fullcalendar/core @fullcalendar/daygrid


// 日历参数

    /*设置日历头部信息,如果设置为false,则不显示头部信息。
     * 包括left,center,right左中右三个位置都可以对应一下配置
     * title:显示当前月份/周、日信息
     * prev:用于切换到上一月/周/日视图的按钮
     * next:用于切换到下一月/周/日视图的按钮
     * prevYear:用于切换到上一年视图的按钮
     * nextYear:用于切换到下一年视图的按钮
     * */
    
    header:{
            left: '',
            center: 'Fullcanlendar示例demo',
            right: 'today prev,next'
            },
    theme:false,//如果设置为true,则需要加载jquery ui相关css和js文件,默认值为false
    firstDay:1,//设置一周中显示的第一天是哪天,周日是0,周一是1,类推
    isRTL:false,//设置为ture时则日历从右往左显示
    weekends:true,//是否显示周末,设为false则不显示周六和周日。默认值为true
    hiddenDays:[],//隐藏一周中的某一天或某几天,数组形式,如隐藏周二和周五:[2,5],默认不隐藏,除非weekends设置为false。
    weekMode:'fixed',//在月视图里显示周的模式,因为每月周数可能不同,所以月视图高度不一定。fixed:固定显示6周高,日历高度保持不变liquid:不固定周数,高度随周数变化variable:不固定周数,但高度固定
    weekNumbers:false,//是否在日历中显示周次(一年中的第几周),如果设置为true,则会在月视图的左侧、周视图和日视图的左上角显示周数。
    weekNumberCalculation:'iso',//周次的显示格式。
    //height:600,//设置日历的高度,包括header日历头部,默认未设置,高度根据aspectRatio值自适应。
    //contentHeight://设置日历主体内容的高度,不包括header部分,默认未设置,高度根据aspectRatio值自适应。
    aspectRatio:1.35,//设置日历单元格宽度与高度的比例。
    handleWindowResize:true,//是否随浏览器窗口大小变化而自动变化。
    render:function(view){
        console.log('render',view)
    },//method,绑定日历到id上。$('#id').fullCalendar('render');
    destroy:function(){
                    
    },
    weekNumbers : false,     //是否在视图左边显示这是第多少周,默认false
        
    eventLimit: true,       //数据条数太多时,限制各自里显示的数据条数(多余的以“+2more”格式显示),默认false不限制,支持输入数字设定固定的显示条数
    
    viewRender : function(view,element){//在视图被渲染时触发(切换视图也触发) 参数view为视图对象,参数element为Jquery的视图Dom
            
    },
    
    dayRender : function(date, cell){//日期格式Render钩子函数(我没理解清楚)
        console.log("↓↓↓dayRender↓↓↓");
        console.log(date);
        console.log(cell);
    },
    windowResize : function(){//浏览器窗体变化时触发
        console.log("---windowResize---");
    },
    
    allDayText : "全天",            //自定义全天视图的名称
    slotDuration : "01:00:00",      //一格时间槽代表多长时间,默认00:30:00(30分钟)
    slotLabelFormat : "H(:mm)a",    //日期视图左边那一列显示的每一格日期时间格式
    slotLabelInterval : "02:00:00", //日期视图左边那一列多长间隔显示一条日期文字(默认跟着slotDuration走的,可自定义)
    snapDuration : "05:00:00",      //其实就是动态创建一个日程时,默认创建多长的时间块
    
    slotEventOverlap : false,       //相同时间段的多个日程视觉上是否允许重叠,默认true允许
    
    noEventsMessage : "L没数据啊",   //listview视图下,无数据时显示提示
    defaultDate  : '2018-09-10',    //默认显示那一天的日期视图getDates(true)
    nowIndicator : true,            //周/日视图中显示今天当前时间点(以红线标记),默认false不显示
    monthNames : ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], //月份自定义命名
    monthNamesShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], //月份缩略命名(英语比较实用:全称January可设置缩略为Jan)
    dayNames: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],       //同理monthNames
    dayNamesShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],  //同理monthNamesShort
    weekNumberTitle : "周",         //周的国际化,默认为"W"
    
    eventLimitText  : "更多",       //当一块区域内容太多以"+2 more"格式显示时,这个more的名称自定义(应该与eventLimit: true一并用)
    dayPopoverFormat : "YYYY年M月d日", //点开"+2 more"弹出的小窗口标题,与eventLimitClick可以结合用
    navLinks : true,                // “xx周”是否可以被点击,默认false,如果为true则周视图“周几”被点击之后进入日视图。本地测试:没什么效果
                  
    dayClick: function(date, jsEvent, view) {//空白的日期区,单击时触发
        console.log("↓↓↓dayClick↓↓↓");
        console.log('Clicked on: ' + date.format());
        console.log('Coordinates: ' + jsEvent.pageX + ',' + jsEvent.pageY);
        console.log('Current view: ' + view.name);
        
        //$(this).css('background-color', 'red');
    },
    eventClick: function(calEvent, jsEvent, view) {//日程区块,单击时触发
        console.log(jsEvent.target)
        alert(jsEvent.target.innerHTML)
        console.log("↓↓↓eventClick↓↓↓");
        console.log('Event: ' + calEvent.title);
        console.log('Coordinates: ' + jsEvent.pageX + ',' + jsEvent.pageY);
        console.log('Current view: ' + view.name);
        
        return false;  //return false可以阻止点击后续事件发生(比如event中的url跳转事件)
    },
    eventMouseover: function(calEvent, jsEvent, view){//鼠标在日程区块上时触发
            
        console.log(jsEvent)
        console.log(calEvent.start._i)
        $('.hover-dateStr').html(calEvent.start._i)
        console.log(jsEvent.pageY,jsEvent.pageX)
        $('.hover-container').removeClass('none').animate({'top':jsEvent.pageY,'left':jsEvent.pageX})
        if(!canRun){
            // 判断是否已空闲,如果在执行中,则直接return
            return;
        }
    },
    eventMouseout: function(calEvent, jsEvent, view){//鼠标从日程区块离开时触发
        $('.hover-container').addClass('none')
    },
    selectable: false,           //允许用户可以长按鼠标选择多个区域(比如月视图,可以选中多天;日视图可以选中多个小时),默认false不能选择多区域的
    selectHelper: true,         //接selectable,周/日视图在选择时是否预先画出“日程区块”的样式出来
    unselectAuto : true,        //是否点击页面上的其他地方会导致当前的选择被清除,默认true
    unselectCancel : "",        //一种方法来指定元素,会忽略unselectauto选项,默认''
    selectOverlap : true,       //确定用户是否被允许选择被事件占用的时间段,默认true可占用时间段
                
    selectAllow : function(selectInfo){ //精确的编程控制用户可以选择的地方,返回true则表示可选择,false表示不可选择
        console.log("↓↓↓selectConstraint↓↓↓");
        console.log("start:"+selectInfo.start+"|end:"+selectInfo.end+"|resourceId:"+selectInfo.resourceId);
        return true;
    },
    select: function(start, end,jsEvent,view) { //点击空白区域/选择区域内容触发
    
    },
    unselect : function(view, jsEvent){//选择操作取消时触发
        console.log("↓↓↓unselect↓↓↓");
        console.log("view:"+view);
    },
                  
    lazyFetching : true,        //是否启用懒加载技术--即只取当前条件下的视图数据,其它数据在切换时触发,默认true只取当前视图的,false是取全视图的
    defaultTimedEventDuration : "02:00:00",     //在Event Object中如果没有end参数时使用,如start=7:00pm,则该日程对象时间范围就是7:00~9:00
    defaultAllDayEventDuration : { days: 1 },  //默认1天是多长,(有的是采用工作时间模式,所以支持自定义)
    loading : function(isLoading, view){ //视图数据加载中、加载完成触发
            console.log("↓↓↓loading↓↓↓");
            if(isLoading == true){
                console.log("view:"+view+",开始加载");
            }else if(isLoading == false){
                console.log("view:"+view+",加载完成");
            }else{
                console.log("view:"+view+",除非天塌下来否则不会进这个分支");
            }
        },
      
    eventOrder : "title",           //多个相同的日程数据排序方式,String / Array / Function, 默认值: "title"
    eventRender : function(event, element, view) {          //当Event对象开始渲染时触发
        console.log("eventRender():"+event.title);
    },
    eventAfterAllRender : function(view){console.log("eventAfterAllRender();");},   //当所有Event对象渲染完成时触发
    editable: true,                 //支持Event日程拖动修改,默认false
    eventStartEditable : true,      //Event日程开始时间可以改变,默认true,如果是false其实就是指日程块不能随意拖动,只能上下拉伸改变他的endTime
    eventDurationEditable : false,  //Event日程的开始结束时间距离是否可以改变,默认true,如果是false则表示开始结束时间范围不能拉伸,只能拖拽
         
    dragOpacity:0.2,                //拖拽时不透明度,0.0~1.0之间,数字越小越透明
    dragScroll : true,              //是否在拖拽时自动移动容器,默认true
    eventOverlap : true,            //拖拽时是否重叠
    eventConstraint : {     //限制拖拽拖放的位置(即限制有些地方拖不进去):an event ID, "businessHours", object
        start: '10:00',     // a start time (10am in this example)
        end: '18:00',       // an end time (6pm in this example)
        dow: [ 1, 2, 3, 4 ] // days of week. an array of zero-based day of week integers (0=Sunday)  (Monday-Thursday in this example)
    },
    longPressDelay : 1000,  //面向可touch设备(如移动设备),长按多少毫秒即可拖动,默认1000毫秒(1S)
    eventDragStart : function(event, jsEvent, ui, view){    //日程开始拖拽时触发
        console.log("eventDragStart():"+event.title);
    },
    eventDragStop : function(event, jsEvent, ui, view){     //日程拖拽停止时触发
        console.log("eventDragStop():"+event.title);
    },
    eventDrop : function(event, delta, revertFunc, jsEvent, ui, view){  //日程拖拽停止并且已经拖拽到其它位置了
        console.log("eventDrop():"+event.title);
    },
    eventResizeStart : function( event, jsEvent, ui, view ) {       //日程大小调整开始时触发
        console.log("eventResizeStart():"+event.title);
    },
    eventResizeStop : function(event, jsEvent, ui, view){           //日程大小调整停止时触发
        console.log("eventResizeStop():"+event.title);
    },
    eventResize : function(event, delta, revertFunc, jsEvent, ui, view){    //日程大小调整完成并已经执行更新时触发
        console.log("eventResize():"+event.title);
    },
    events:[
                {
                    "time": "9:20--18:20",
                    "antualTime":"9:40--18:40",
                    "start": "2018-09-01"
                    
                },
                {
                    "time": "9:40--18:40",
                    "antualTime":"9:40--18:40",
                    "start": "2018-09-02"
                }
            ]



<!--日历管理-->
<template>
  <a-card bordered>
    <full-calendar :options="calendarOptions">
      <!-- 想要实现 点击事件弹出对应位置的弹框必须使用 <template v-slot:eventContent="arg">这个指令 -->
      <template v-slot:eventContent="arg">
        <!-- 这里使用AntUI 提供的popover/TipTop标签 -->
        <a-popover title="日程" trigger="click">
          <template slot="content">
            <div>
              <a-icon type="robot" />
              <!-- 如果不知道(v-slot:eventContent="arg")中的arg是什么数据结构可以看看 -->
              <!-- {{ arg }} -->
              {{ arg.event.extendedProps.equipmentId }}
            </div>
            <div style="padding-top: 12px">
              <div
                style="
                  display: inline-block;
                  height: 10px;
                  width: 10px;
                  border-radius: 8px;
                  background: #00b853;
                  margin-right: 7px;
                "
              ></div>
              <span>{{ arg.event.title }}</span>
            </div>
            <div style="padding-top: 12px">
              <a-icon type="clock-circle" />
              {{ arg.event.extendedProps.nextPmTime }}
            </div>
            <!-- <a-divider /> -->
            <p style="text-align: right">
              <a @click="detail" style="font-size: 16px"
                ><a-icon type="eye" />{{ "详情" }}</a
              >
            </p>
          </template>
          <b>{{ arg.event.title }}</b>
        </a-popover>
      </template>
    </full-calendar>
  </a-card>
</template>

<script>
// 引入moment时间格式化
import moment from "moment";
//农历计算方法 (在我博客里面可以找到.js文件)
import calendar from "@/utils/calendar";
// 引入FullCalendar所需插件
import FullCalendar from "@fullcalendar/vue";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import listPlugin from "@fullcalendar/list";
export default {
  // 插入FullCalendar组件
  components: { FullCalendar },
  data() {
    return {
      // 存储点击日程数据
      clickInfo: [],
      // 日历参数
      calendarOptions: {
        plugins: [dayGridPlugin, interactionPlugin, timeGridPlugin, listPlugin],
        // 数据存储
        // 参考数据
        // events: [
        //   { title: 'event 1', date: '2020-06-01',classNames:['cal'] },
        //   { title: 'event 2', date: '2020-06-02',classNames:['inv'] },
        //   { title: '公司会议', start: '2020-06-22 09:05', end:'2020-06-23 12:00',classNames:['cal'] },
        //   { title: '部门会议', start: new Date(),classNames:['cal'] },
        // ],
        events: [],
        // 头部导航
        headerToolbar: {
          left: "prev,next title",
          center: "",
          right: "now dayGridMonth,timeGridWeek,timeGridDay,listDay",
        },
        // 按钮信息
        buttonText: {
          month: "月",
          week: "周",
          day: "日",
          list: "列表视图",
        },
        views: {
          //对应月视图
          dayGridMonth: {
            displayEventTime: false, //是否显示时间
            dayCellContent(item) {
              let _date = moment(item.date).format("YYYY-MM-DD").split("-");
              let _dateF = calendar.solar2lunar(_date[0], _date[1], _date[2]);
              return {
                html: `<p><label>${_dateF.cDay}</label><span>${_dateF.IDayCn}</span></p>`,
              };
            },
          },
          //对应周视图
          timeGridWeek: {
            slotMinTime: "09:00", //周视图开始时间
            slotMaxTime: "20:00", //周视图结束时间
            displayEventTime: false, //是否显示时间
            dayHeaderContent(item) {
              let _date = moment(item.date).format("YYYY-MM-DD").split("-");
              let _dateF = calendar.solar2lunar(_date[0], _date[1], _date[2]);
              return {
                html: `<h3>${_dateF.ncWeek.slice(2)}</h3><p><label>${
                  _dateF.cDay
                }</label><span>${_dateF.IDayCn}</span></p>`,
              };
            },
          },
          //对应天视图
          timeGridDay: {
            dayHeaderContent(item) {
              return { html: `<h3>${item.text}</h3>` };
            },
          },
        },
        slotLabelFormat: {
          hour: "2-digit",
          minute: "2-digit",
          meridiem: false,
          hour12: false, //设置时间为24小时
        },
        // 自定义按钮
        customButtons: {
          //今天
          now: {
            text: "今天",
            click: () => {
              this.$refs.myCalendar.getApi().today();
            },
          },
        },
        initialView: "dayGridMonth", //初始视图
        // initialEvents: [],
        locale: "zh-cn", //语言
        // themeSystem: "bootstrap", //主题(仅支持插件提供UI主题)
        allDayText: "", //allDay时间
        displayEventEnd: true, //所有视图显示结束时间
        dateClick: this.handleDateClick,
        editable: true,
        selectable: true,
        selectMirror: true,
        dayMaxEvents: true,
        weekends: true,
        // select: this.handleDateSelect, //选择日期事件,可响应一个新建日程的事件
        // eventDrop: this.handleEventDrop, //拖动事件
        // eventResize: this.handleEventResize,
        eventClick: this.handleEventClick, //点击事件对象事件
        // eventsSet: this.handleEvents,
      },
    };
  },
  created() {
    this.loadCalendar();
  },
  methods: {
    // 添加事件
    // handleDateSelect(selectInfo) {},
    // handleEventDrop(info){},

    // 点击日程事件(新建日程)
    handleEventClick(clickInfo) {
      this.clickInfo = clickInfo;
    },

    detail() {
      // 项目中我点击详情按钮(a链接)以组件的方式链接到另一个页面
      // 这个事件可删(根据项目需求)
    },
    // 日历数据加载
    loadCalendar() {
      // queryPmByList 是发送请求的api
      queryPmByList({
        searchDate: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
      }).then((res) => {
        // 根据后台对应的值转换成 FullCalendar 插件 使用的数据格式(警示: 必须要按照FullCalendar格式字段名,否则无效)
        res.msgBody.forEach((item) => {
          item.date = item.nextPmTime;
          item.title = item.scheduleId;
          // classNames  是我再css样式中自定义的类名  用于修改日程背景颜色(根据后台传的状态进行设置,如果后台没有可以不用管)
          if (item.inhibitflg) {
            item.classNames = ["ord"];
          } else if (!item.pmJobExists) {
            item.classNames = ["inv"];
          } else if (item.canCreateOrder) {
            item.classNames = ["cal"];
          } else {
            item.classNames = ["oth"];
          }
        });
        // 最后将值赋值给 FullCalendar 插件存储数据的位置
        this.calendarOptions.events = res.msgBody;
      });
    },
    // 国际化事件(不需要可删,根据项目需求)
    calendarLocal() {
      this.calendarOptions.allDayText = this.$t("lang.message.allDay"); // 全天国际化
      this.calendarOptions.buttonText.month = this.$t("lang.button.month"); // 视图月按钮国际化
      this.calendarOptions.buttonText.week = this.$t("lang.button.week"); // 视图周按钮国际化
      this.calendarOptions.buttonText.day = this.$t("lang.button.day"); // 视图天按钮国际化
      this.calendarOptions.buttonText.list = this.$t("lang.button.list"); // 列表视图按钮国际化
      this.calendarOptions.customButtons.now.text = this.$t(
        "lang.button.today"
      ); // 今天按钮国际化
    },
  },
  computed: {
    // 用户登录获取store里面的当前语言是英文 还是中文
    calendarLocale() {
      return this.$store.state.lang.locale;
    },
  },
  watch: {
    // 获取到store里面的当前语言并赋值给FullCalendar插件里面的国际化识别
    calendarLocale(val) {
      this.calendarOptions.locale = val;
      // 由于FullCalendar国际化存在BUG所以将需要国际化的文字存放在这个数组
      this.calendarLocal();
    },
  },
};
</script>
// 新版日历
<style lang="less">
.ant-alert.ant-alert-no-icon {
  padding: 0px;
}
.fc-daygrid-event {
  .fc-daygrid-event-dot {
    display: none;
  }
  &.cal {
    padding-left: 5px;
    color: #333;
    border-radius: 0;
    border: none;
    border-left: 2px solid #52c41a;
    background-color: #52c41a;
    .fc-event-title {
      color: #fff;
    }
  }
  &.inv {
    padding-left: 5px;
    color: #333;
    border-radius: 0;
    border: none;
    border-left: 2px solid #189dff;
    background-color: #189dff;
    .fc-event-title {
      color: #fff;
    }
  }
  &.ord {
    padding-left: 5px;
    color: #fff;
    border-radius: 0;
    border: none;
    border-left: 2px solid #000000;
    background-color: #000000;
    .fc-event-title {
      color: #fff;
    }
  }
  &.oth {
    padding-left: 5px;
    color: #333;
    border-radius: 0;
    border: none;
    border-left: 2px solid silver;
    background-color: silver;
    .fc-event-title {
      color: #000;
    }
  }
}
.fc .fc-toolbar-title {
  display: inline-block;
  vertical-align: middle;
}
.fc-theme-standard td {
  border-top-color: transparent;
}
.fc .fc-button {
  height: 30px;
  line-height: 1.2em;
}
.fc .fc-toolbar-title {
  font-size: 1.2em;
}
.fc .fc-button .fc-icon {
  font-size: 1em;
}
.fc .fc-button-primary {
  background-color: #fff;
  border: 1px solid #037bff;
  color: rgba(0, 0, 0, 0.65);
}
.fc .fc-button-primary:hover {
  background-color: #fff;
  border: 1px solid #037bff;
  color: #299bff;
}
.fc .fc-button-primary:not(:disabled):active:focus,
.fc .fc-button-primary:not(:disabled).fc-button-active:focus,
.fc .fc-button:focus {
  box-shadow: none;
}
.fc .fc-button-primary:not(:disabled):active,
.fc .fc-button-primary:not(:disabled).fc-button-active {
  background-color: #fff;
  border: 1px solid #037bff;
  color: #299bff;
}
.fc .fc-button-primary:disabled,
.fc .fc-button-primary:disabled:hover {
  background-color: #f5f5f5;
  border-color: #d9d9d9;
  color: rgba(0, 0, 0, 0.25);
}
.fc-v-event .fc-event-main {
  color: #333;
}
.ant-popover {
  width: 25%;
}
</style>

 

posted on 2021-03-15 10:05  ㅤㅤㅤㅤㅤㅤ  阅读(1400)  评论(0编辑  收藏  举报

导航