FullCalendar 二次封装使用指定显示月份

64 min read
<template>
  <FullCalendar
    ref="fullCalendar"
    :options="calendarOptions"
  />
</template>

<script lang="ts" setup>
import '@fullcalendar/core/vdom' // solve problem with Vite
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction'
import FullCalendar from '@fullcalendar/vue3'
import type { PropType } from 'vue'

const props = defineProps({
  // 修改默认语言
  local: {
    type: String,
    default: 'zh-cn',
  },
  // 初始化视图
  initialView: {
    type: String,
    default: 'dayGridMonth',
  },
  // 按钮配置
  buttonText: {
    type: Object,
    default: () => {
      return {
        today: '今天',
        month: '月',
        week: '周',
        day: '日',
        prevYear: '上一年',
        nextYear: '下一年',
        prev: '上一月',
        next: '下一月',
      }
    },
  },
  headerToolbar: {
    type: Object,
    default: () => {
      return {
        start: 'title',
        center: '',
        end: 'prev today next',
      }
    },
  },

  validRange: {
    type: Object,
    default: () => {
      return {
        start: '2019-01-01',
        end: '2099-01-01',
      }
    },
  },

  // 日期事件对象
  events: {
    type: Array as PropType<EventItem[]>,
    default: () => [],
  },

  eventContent: {
    type: Function,
  },

  date: {
    type: String,
    default: '',
  },
})

const emits = defineEmits(['date-click', 'event-click', 'select-range'])

interface EventItem {
  title: string
  start: string
  end: string
  editable?: boolean
}

const fullCalendar = ref()

const calendarOptions = computed(() => ({
  plugins: [dayGridPlugin, interactionPlugin],
  initialView: props.initialView,
  locale: props.local,
  buttonText: props.buttonText,
  headerToolbar: props.headerToolbar,
  events: props.events,
  validRange: props.validRange,
  selectable: true,
  // eventSources: [
  //   {
  //     events(e, callback) {
  //       if (props.events.length)
  //         callback(props.events)
  //       else callback([])
  //     },
  //   },
  // ],
  dateClick(info) {
    // fullCalendar.value?.getApi().destroy()
    // eslint-disable-next-line vue/custom-event-name-casing
    emits('date-click', info)
  },
  eventClick(info) {
    // eslint-disable-next-line vue/custom-event-name-casing
    emits('event-click', info)
  },
  select(info) {
    // eslint-disable-next-line vue/custom-event-name-casing
    emits('select-range', info)
  },
  displayEventEnd: true,
  eventContent: props.eventContent,
}))

onMounted(() => {
  fullCalendar.value?.getApi().render()
})

watch(() => props.date, () => {
  fullCalendar.value?.getApi().gotoDate(props.date)
})
</script>

<style>
.fc{
  height: 100%;
}
</style>