Fullcalendar多事件源冲突处理:删除冲突的可用时段事件
Hey Christophe, let's break down how to solve this problem you've been stuck on for a few days. Here's a step-by-step approach that should work smoothly:
1. 给两类事件添加区分标识
First, make sure you can easily tell apart your "available" and "occupied" events. When setting up your eventSources, add a custom property to each event (or the event source itself) to categorize them. For example:
// 可用时段事件源 { url: '/api/available-slots', eventDataTransform: function(eventData) { return { ...eventData, eventType: 'available' // 自定义标识,用于后续区分 }; } } // 用户已占用事件源 { url: '/api/occupied-slots', eventDataTransform: function(eventData) { return { ...eventData, eventType: 'occupied' // 自定义标识,用于后续区分 }; } }
This way, you can filter events by eventType later using FullCalendar's event retrieval methods.
2. 编写时间冲突判断函数
You'll need a helper function to check if two events overlap. FullCalendar events have start and end properties (either Moment.js objects for older versions, or native Date objects for v5+), so we can use those to compare:
// 适用于FullCalendar v4及以下(Moment.js) function doEventsOverlap(eventA, eventB) { // 两个事件重叠的核心条件:A开始于B结束前,且A结束于B开始后 return eventA.start.isBefore(eventB.end) && eventA.end.isAfter(eventB.start); } // 适用于FullCalendar v5+(原生Date对象) function doEventsOverlap(eventA, eventB) { return eventA.start < eventB.end && eventA.end > eventB.start; }
3. 在事件加载完成后执行冲突检查与删除
You need to run this logic after all events have finished loading to ensure you're comparing the full dataset. Use FullCalendar's eventSourcesSet callback (or viewDidMount if you're using the React wrapper) to trigger the process:
document.addEventListener('DOMContentLoaded', function() { var calendarEl = document.getElementById('calendar'); var calendar = new FullCalendar.Calendar(calendarEl, { // 其他日历配置... eventSources: [/* 你的两个事件源 */], eventSourcesSet: function() { // 筛选出两类事件 const occupiedEvents = calendar.getEvents().filter(event => event.extendedProps.eventType === 'occupied'); const availableEvents = calendar.getEvents().filter(event => event.extendedProps.eventType === 'available'); // 找出所有和已占用事件冲突的可用时段事件 const conflictingAvailableEvents = availableEvents.filter(availableEvent => { return occupiedEvents.some(occupiedEvent => doEventsOverlap(availableEvent, occupiedEvent)); }); // 删除冲突的可用时段事件 conflictingAvailableEvents.forEach(event => { event.remove(); }); } }); calendar.render(); });
额外优化建议
- 如果你的事件源会动态更新(比如用户新增了占用事件),记得在事件更新后重新触发冲突检查逻辑——可以放在
eventAdd或eventChange回调里。 - 要是可用时段事件数量很大,你可以优化性能:先把两类事件按开始时间排序,减少不必要的对比次数,但对于大多数业务场景,上面的基础逻辑已经足够好用。
内容的提问来源于stack exchange,提问作者Christophe N

