FullCalendar长周期事件如何禁用节假日等指定日期
FullCalendar 长周期课程事件跳过节假日展示方案
核心实现逻辑不需要修改原始业务事件数据,通过事件加载阶段的预处理拆分长周期事件,即可实现节假日时段自动隐藏长课程,不影响固定日期的短课程正常展示,步骤如下:
- 先维护本地节假日日期集合,统一使用
YYYY-MM-DD格式存储,避免时分秒、时区问题导致匹配失效:
// 节假日日期集合,可根据每年官方放假安排动态更新 const holidaySet = new Set([ '2022-06-03', '2022-09-10', '2022-10-01', '2022-10-02', '2022-10-03' // 其余节假日按相同格式补充即可 ])
- 替换原有静态
events配置为动态回调,在回调里区分两类事件处理:- 带
multi_day: "selected"标记的固定日期短事件(单次音乐/拳击/语言课),本身不会排期在节假日,直接透传展示即可 - 带
end字段的跨月长周期课程,遍历事件覆盖的日期区间,遇到节假日就截断事件段,自动跳过假期拆分出多个连续的非假期事件段,交给日历渲染
- 带
- 完整配置示例:
const calendarEl = document.getElementById('calendar') const calendar = new FullCalendar.Calendar(calendarEl, { initialView: 'dayGridMonth', // 替换原有静态events配置 events: (fetchInfo, successCallback) => { // 原始事件数据,直接替换为你现有接口返回/本地定义的events数组即可 const rawEvents = [ { "title": "selected dates Events", "allDay": false, "start": "2022-06-16T15:03:00", "unformated_date": "June 16, 2022", "url": "http://localhost:8888/boxingstudio/product/selected-dates-events/", "post_id": 536, "multi_day": "selected", "color": "#16a75d", "textColor": "#ffffff", "in_stock": "yes" }, { "title": "selected dates Events", "allDay": false, "start": "2022-06-23T15:03:00", "unformated_date": "", "url": "http://localhost:8888/boxingstudio/product/selected-dates-events/", "post_id": 536, "multi_day": "selected", "color": "#16a75d", "textColor": "#ffffff", "in_stock": "yes" }, { "title": "selected dates Events", "allDay": false, "start": "2022-06-25T15:03:00", "unformated_date": "June 25, 2022", "url": "http://localhost:8888/boxingstudio/product/selected-dates-events/", "post_id": 536, "multi_day": "selected", "color": "#16a75d", "textColor": "#ffffff", "in_stock": "yes" }, { "title": "selected dates Events", "allDay": false, "start": "2022-06-26T15:03:00", "unformated_date": "June 26, 2022", "url": "http://localhost:8888/boxingstudio/product/selected-dates-events/", "post_id": 536, "multi_day": "selected", "color": "#16a75d", "textColor": "#ffffff", "in_stock": "yes" }, { "title": "selected dates Events", "allDay": false, "start": "2022-06-29T15:03:00", "unformated_date": "June 29, 2022", "url": "http://localhost:8888/boxingstudio/product/selected-dates-events/", "post_id": 536, "multi_day": "selected", "color": "#16a75d", "textColor": "#ffffff", "in_stock": "yes" }, { "title": "New Kick Boxing Product 1233", "allDay": false, "start": "2022-06-23T00:00:00", "unformated_date": "June 23, 2022", "url": "http://localhost:8888/boxingstudio/product/new-kick-boxing-product-1233/", "post_id": 535, "color": "#16a75d", "textColor": "#ffffff", "end": "2024-04-19T00:00:00", "unformated_end_date": "April 19, 2024", "in_stock": "yes" }, { "title": "Kick Boxing Test", "allDay": false, "start": "2022-06-20T03:02:00", "unformated_date": "June 20, 2022", "url": "http://localhost:8888/boxingstudio/product/kick-boxing-test/", "post_id": 531, "color": "#16a75d", "textColor": "#ffffff", "end": "2022-07-18T14:02:00", "unformated_end_date": "July 18, 2022", "in_stock": "yes" } ] const processed = [] rawEvents.forEach(ev => { // 短事件直接透传 if (!ev.end || ev.multi_day === 'selected') { processed.push(ev) return } // 拆分长周期事件 const evStart = new Date(ev.start) const evEnd = new Date(ev.end) let segStart = new Date(evStart) const curDate = new Date(evStart) while (curDate <= evEnd) { const dateStr = curDate.toISOString().split('T')[0] // 碰到节假日,截断之前的非假期段 if (holidaySet.has(dateStr)) { if (segStart < curDate) { processed.push({ ...ev, start: new Date(segStart), end: new Date(curDate) }) } // 跳过假期,设置新段起点为假期后一天 segStart = new Date(curDate) segStart.setDate(segStart.getDate() + 1) } curDate.setDate(curDate.getDate() + 1) } // 补入最后一段非假期区间 if (segStart < evEnd) { processed.push({ ...ev, start: new Date(segStart), end: new Date(evEnd) }) } }) successCallback(processed) } }) calendar.render()
版本兼容提示:如果使用v4及更早版本的FullCalendar,把上述事件拆分逻辑挪到
eventDataTransform钩子中执行即可,核心判断逻辑不需要改动。
- 后续维护技巧:如果需要动态更新节假日列表,更新
holidaySet集合后调用calendar.refetchEvents()就能即时刷新日历视图,不需要重新初始化实例。
内容的提问来源于stack exchange,提问作者Karthikvijayaveni
相关产品推荐
相关产品推荐

