taskCalendar.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <template>
  2. <div class="w-full h-full flex flex-col">
  3. <div class="flex-1" v-loading="calendarLoading">
  4. <FullCalendar ref="calendarRef" :options="calendarOptions" class="h-full w-full">
  5. <template v-slot:eventContent='arg'>
  6. <div>{{ arg.event.title }}</div>
  7. </template>
  8. </FullCalendar>
  9. </div>
  10. </div>
  11. </template>
  12. <script setup lang="ts">
  13. import { ref, onMounted } from 'vue';
  14. import FullCalendar from '@fullcalendar/vue3';
  15. import dayGridPlugin from '@fullcalendar/daygrid';
  16. import timeGridPlugin from '@fullcalendar/timegrid'
  17. import interactionPlugin from '@fullcalendar/interaction'
  18. import zhCnLocale from '@fullcalendar/core/locales/zh-cn'
  19. import { post, uploadFile } from '@/utils/request';
  20. import { GET_TASK_LIST_BY_START_AND_END } from './api'
  21. import { formatDate, getFirstDayOfMonth, getLastDayOfMonth } from '@/utils/times';
  22. import { dayjs } from 'element-plus';
  23. // 当前选中的视图
  24. const currentView = ref('dayGridMonth')
  25. // 日历实例引用
  26. const calendarRef = ref()
  27. const dateForm = ref({
  28. startDate: getFirstDayOfMonth(new Date()),
  29. endDate: getLastDayOfMonth(new Date())
  30. })
  31. const calendarListData = ref([])
  32. const calendarLoading = ref(false)
  33. // FullCalendar 配置
  34. const calendarOptions = ref<any>({
  35. plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin],
  36. locale: zhCnLocale,
  37. initialView: currentView.value,
  38. slotMinTime: '06:00:00', // 最早显示时间
  39. slotMaxTime: '22:00:00', // 最晚显示时间
  40. slotDuration: '00:30:00', // 30分钟一格(timeGrid生效)
  41. events: [],
  42. headerToolbar: { // 自定义头部
  43. left: 'today,prev,next', // 左侧按钮:上一页,下一页,今天
  44. center: 'title',
  45. right: 'dayGridMonth,timeGridWeek,timeGridDay' // 右侧显示视图切换按钮
  46. },
  47. datesSet: (arg: any) => { // 📌 每次切换视图或日期都会触发
  48. const { startStr = '', endStr = '' } = arg
  49. if (startStr && endStr) {
  50. dateForm.value = {
  51. startDate: startStr,
  52. endDate: endStr,
  53. }
  54. getTaskCalendar()
  55. }
  56. }
  57. })
  58. // 重新渲染表格数据
  59. function renderTableData() {
  60. calendarOptions.value = {
  61. ...calendarOptions.value,
  62. events: (calendarListData.value || []).map((item: any) => {
  63. return {
  64. ...item,
  65. start: item.startDate,
  66. end: item.endDate,
  67. title: item.taskName
  68. }
  69. })
  70. }
  71. }
  72. function getTaskCalendar() {
  73. const { startDate, endDate } = dateForm.value
  74. calendarLoading.value = true
  75. post(GET_TASK_LIST_BY_START_AND_END, {
  76. startDate: dayjs(startDate).format('YYYY-MM-DD'),
  77. endDate: dayjs(endDate).format('YYYY-MM-DD')
  78. }).then((res) => {
  79. calendarListData.value = res.data || []
  80. renderTableData()
  81. }).finally(() => {
  82. calendarLoading.value = false
  83. })
  84. }
  85. onMounted(() => {
  86. getTaskCalendar()
  87. })
  88. defineExpose({
  89. getTaskCalendar
  90. })
  91. </script>
  92. <style lang="scss" scoped>
  93. :deep(.fc-today-button) {
  94. margin-right: 10px;
  95. }
  96. </style>