美文网首页
Vue日历,FullCalendar 使用及兼容IE10+

Vue日历,FullCalendar 使用及兼容IE10+

作者: ErHu丶 | 来源:发表于2020-08-12 14:14 被阅读0次

    FullCalendar v4.1.0版本

    效果图(月)
    效果图(周)

    以下是部分代码,看懂逻辑即可:

    // package.json 引入
    "dependencies": {
        "@fullcalendar/core": "^4.1.0",
        "@fullcalendar/daygrid": "^4.1.0",
        "@fullcalendar/interaction": "^4.1.0",
        "@fullcalendar/timegrid": "^4.1.0",
        "@fullcalendar/vue": "^4.1.0"
    }
    

    IE10需要单独引入此方法:
    Intl.complete.js 来源: https://github.com/andyearnshaw/Intl.js/blob/master/dist/Intl.complete.js

      <!-- 日历组件支持IE10 -->
      <script type="text/javascript" src="./vendor/Intl.complete.js"></script>
      <script>window.Intl = window.IntlPolyfill</script>
      <!-- popper 弹窗库 -->
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/jquery.webui-popover/1.2.18/jquery.webui-popover.min.css">
      <script src="//cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script>
      <script src="https://cdn.jsdelivr.net/jquery.webui-popover/1.2.18/jquery.webui-popover.min.js"></script>
    

    对应页面的初始化代码。

    <template>
      <div class="calendar-container">
        <FullCalendar
          ref="calendar"
          v-loading="loading"
          class="calendar"
          :style="{ width: calendarOptions.width + 'px' }"
          :locale="calendarOptions.locale"
          :default-view="calendarOptions.initialView"
          :buttonText="calendarOptions.buttonText"
          :header="calendarOptions.headerToolbar"
          :plugins="calendarOptions.plugins"
          :all-day-slot="calendarOptions.allDaySlot"
          :height="calendarOptions.height"
          :custom-buttons="calendarOptions.customButtons"
          :slot-duration="calendarOptions.slotDuration"
          :slot-label-interval="calendarOptions.slotLabelInterval"
          :slot-min-time="calendarOptions.slotMinTime"
          :slot-max-time="calendarOptions.slotMaxTime"
          :scroll-time="calendarOptions.scrollTime"
          :slot-label-format="calendarOptions.slotLabelFormat"
          :event-time-format="calendarOptions.eventTimeFormat"
          :events="getCalendarEvents"
          @datesRender="datesRender"
          @eventMouseEnter="eventMouseEnter"
        />
        <popper v-show="false" :data-item="popperData"></popper>
      </div>
    </template>
    
    <script>
    // See https://fullcalendar.io/docs#toc version: v4!
    import FullCalendar from '@fullcalendar/vue'
    import dayGridPlugin from '@fullcalendar/daygrid'
    import timeGridPlugin from '@fullcalendar/timegrid'
    import interactionPlugin from '@fullcalendar/interaction'
    import cnLocale from '@fullcalendar/core/locales/zh-cn'
    import Popper from './Popper.vue'
    import { mapGetters } from 'vuex'
    import defaultSettings from '@/settings.js'
    
    export default {
      name: 'Calendar',
      components: {
        FullCalendar,
        Popper
      },
      props: {
        loading: {
          type: Boolean,
          required: true,
          default: () => false
        }
      },
      computed: {
        ...mapGetters({
          calendarData: 'teacher/calendarData',
        })
      },
      watch: {
        calendarData: {
          immediate: true,
          handler(newVal) {
            this.configCalendarData(newVal)
          }
        }
      },
      data() {
        const _this = this
        return {
          calendarOptions: {
            locale: cnLocale,
            plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin],
            headerToolbar: { // 配置Header的操作按钮和位置
              left: 'timeGridWeek,dayGridMonth',
              center: 'prev title next today',
              right: 'allCourseButton'
            },
            buttonText: {
              today: '本周'
            },
            customButtons: {
              allCourseButton: {
                text: '查看所有课程',
                click: function() {
                  _this.$router.push('/teacher/list')
                }
              }
            },
            height: 795, // 日历高度
            slotLabelInterval: '00:15', // 时间间隔
            slotDuration: '00:15:00', // 时间间隔
            slotMinTime: '00:00',
            slotMaxTime: '24:00',
            scrollTime: '08:00', // 默认展示的时间
            slotLabelFormat: { // 周时间的左侧时间轴配置
              hour12: false,
              hour: '2-digit',
              minute: '2-digit'
            },
            eventTimeFormat: {
              hour12: false,
              hour: '2-digit',
              minute: '2-digit'
            },
            allDaySlot: false,
            events: this.getCalendarEvents,
            eventMouseEnter: this.eventMouseEnter,
            initialView: 'timeGridWeek' // 初始化时展示的类型
          },
          calendarEvents: [],
          calendarApi: '', // 日历实例
          popperData: {}, // 当前弹窗的数据
          currentPopper: false, // 当前弹窗的实例
          eventControl: false, // 用于事件节流
          containerWidth: 800 // 用于判断弹出窗口朝左还是朝右
        }
      },
      mounted() {
        // 日历的实例
        this.calendarApi = this.$refs.calendar.getApi()
        // 获取页面宽度高度, 需要用到
        const container = document.querySelector('.teacher-schedule-container')
        this.calendarOptions.height = container.clientHeight
        this.containerWidth = container.clientWidth
      },
      methods: {
        datesRender(info) {
          // 日历类型改变回调
          if (info.view.type === 'dayGridMonth') {
            $('.fc-today-button').text('本月')
          } else if (info.view.type === 'timeGridWeek') {
            $('.fc-today-button').text('本周')
          }
        },
        eventMouseEnter(event) {
          // 设置弹窗数据
          this.$set(this, 'popperData', event.event.extendedProps)
          const el = $(event.el)
          const offset = event.el.getBoundingClientRect()
          const position = offset.right
          this.$nextTick(() => {
            // 根据位置弹出汽泡
            // See: https://github.com/sandywalker/webui-popover
            el.webuiPopover({
              // 如果位置太靠右就在左侧显示
              placement: position + 300 > this.containerWidth ? 'left' : 'right',
              container: document.body,
              trigger: 'hover',
              url: '#popper',
              padding: false,
              animation: 'pop',
              cache: false,
              onShow: () => {
                // 隐藏原有Dom上的元素
                $('.calendar-container .popper-container').hide()
                try {
                  // 添加点击事件, 原Dom上的加不了, 只能这样加
                  $('body .popper-container .live-button').last().click(() => {
                    // 弹窗上的按钮点击了
                  })
                } catch (e) {
                  // eslint-disable-next-line
                }
              },
              onHide: () => {
                el.webuiPopover('destroy')
              }
            })
            el.webuiPopover('show')
          })
        },
        getCalendarEvents(info, cbk) {
          // 返回日历的事件集合
          cbk(this.calendarEvents)
        },
        configCalendarData(datas) {
          // 配置日历数据源
          let events = []
          for (let i = 0; i < datas.length; i++) {
            const item = datas[i]
            const color = item.Status === '已结束' ? '#adadad' : '#ff9c5a'
            events.push({
              id: item.HourGuid,
              backgroundColor: color,
              borderColor: color,
              title: item.HourName,
              extendedProps: item,
              start: new Date(item.HourStart.replace(/-/g, '/')), // IE不支持 2019-01-01, 支持2019/01/01
              end: new Date(item.HourEnd.replace(/-/g, '/'))
            })
          }
          this.calendarEvents = events
          this.calendarApi.refetchEvents()
        }
      }
    }
    </script>
    
    <style type="text/css">
    /* 气泡弹窗UI */
      .webui-popover {
        border: 0 !important;
        box-shadow: 0 1px 10px rgba(0,0,0,.2) !important;
      }
    
      .webui-popover .webui-arrow {
        border-right-color: #f0f0f0 !important;
        border-left-color: #f0f0f0 !important;
      }
    
    </style>
    
    <style lang="scss" scoped>
    
    @import '~@fullcalendar/core/main.css';
    @import '~@fullcalendar/daygrid/main.css';
    @import '~@fullcalendar/timegrid/main.css';
    
      .calendar-container {
        width: calc(100vw - 80px);
        min-width: 1120px;
    
        // 头部操作按钮相关CSS
        ::v-deep .fc-header-toolbar {
          display: flex;
    
          .fc-button {
            background-color: #fff;
            border: 1px solid #dcdfe6;
            color: #418aec;
            font-size: 14px;
          }
    
          .fc-center {
            display: flex;
          }
    
          .fc-button-active {
            background-color: #418aec;
            border: 1px solid #418aec;
            color: #fff;
          }
    
          .fc-button:focus {
            box-shadow: none;
          }
    
          .fc-timeGridWeek-button, .fc-dayGridMonth-button {
            padding: 8px 30px;
          }
    
          .fc-allCourseButton-button {
            border: 0;
            background-color: #418aec;
            color: #fff;
            // font-size: 13px;
            padding: 8px 18px;
          }
    
          .fc-today-button {
            font-weight: bold;
            border: 0;
            padding-left: 20px;
          }
        }
    
        // 周日历事件相关CSS
        ::v-deep .fc-time-grid {
          .fc-title {
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
          }
    
          .fc-time-grid-event {
            padding: 5px;
            font-weight: bold;
          }
    
        }
    
        ::v-deep .fc-day-grid-container .fc-title {
          position: absolute;
          left: 45px;
          right: 0;
          text-overflow: ellipsis;
          overflow: hidden;
        }
    
        // 修改非当月日期背景色为灰色
        ::v-deep .fc-other-month {
          background-color: #f0f0f0;
        }
    
        // 修改当天在日历中的背景颜色
        ::v-deep .fc-today {
          background-color: #fff;
        }
      }
    </style>
    

    Popper 组件内容:

    <template>
      <div id="popper" ref="popper" class="popper-container">
        <div class="content">名称: {{ dataItem.Name }}</div>
        <!-- 省略其他字段 -->
        <el-button round class="live-button">可点击按钮</el-button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'Popper',
      props: {
        dataItem: {
          type: Object,
          required: false,
          default: () => {}
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    
      .popper-container {
        background: #fff;
        padding: 15px 20px;
        font-size: 15px;
        border-radius: 4px;
        z-index: -1;
        width: 200px !important;
        text-align: center;
        max-height: 300px !important;
        overflow-y: auto;
        display: none;
    
        .content {
          font-size: 14px;
          line-height: 20px;
          padding-bottom: 10px;
          text-align: left;
        }
    
        .live-button {
          border-color: #418aec;
          background-color: #418aec;
          margin-top: 10px;
          margin-bottom: 5px;
          width: 160px;
        }
      }
    </style>
    

    相关文章

      网友评论

          本文标题:Vue日历,FullCalendar 使用及兼容IE10+

          本文链接:https://www.haomeiwen.com/subject/ateqvhtx.html