如何在FullCalendar主事件首尾添加固定时长的准备与收尾时段
绑定主事件准备/收尾时段的FullCalendar v5.10.1实现方案
核心思路
放弃创建独立的准备/收尾事件,转而通过扩展主事件属性+自定义渲染+内置事件钩子实现需求:把准备/收尾时段作为主事件的一部分计算时间范围,用渲染区分样式,靠FullCalendar原生机制处理同步和重叠,彻底解决性能和关联失效问题。
1. 给主事件添加自定义属性
在主事件数据中加入准备、收尾的时长参数,用于后续计算完整时间范围:
// 示例主事件数据 { id: 'conf-room-1', title: '会议室A租赁', start: '2024-05-20T10:00:00', end: '2024-05-20T12:00:00', prepDuration: 30, // 准备时长(分钟) wrapupDuration: 30, // 收尾时长(分钟) editable: true, // 主事件可编辑 isMainEvent: true // 标记为主事件 }
2. 实现完整范围的重叠阻止
利用eventOverlap回调,计算主事件包含准备/收尾的完整时间范围,阻止其他事件与该范围重叠:
eventOverlap: function(stillEvent, movingEvent) { if (!movingEvent.extendedProps.isMainEvent) return true; // 计算主事件的完整占用时间(准备+主时段+收尾) const prepStart = moment(movingEvent.start).subtract(movingEvent.extendedProps.prepDuration, 'minutes').toDate(); const wrapupEnd = moment(movingEvent.end).add(movingEvent.extendedProps.wrapupDuration, 'minutes').toDate(); // 判断其他事件是否与完整范围重叠 return !( moment(stillEvent.start).isBefore(wrapupEnd) && moment(stillEvent.end).isAfter(prepStart) ); }
3. 同步准备/收尾与主事件的移动、调整
监听主事件的拖拽和调整事件,触发重新渲染即可自动同步准备/收尾时段,无需重建事件:
document.addEventListener('DOMContentLoaded', function() { const calendar = new FullCalendar.Calendar(document.getElementById('calendar'), { // 其他基础配置 eventDrop: function(info) { if (info.event.extendedProps.isMainEvent) { calendar.refetchEvents(); // 触发重渲染,自动同步准备/收尾位置 } }, eventResize: function(info) { if (info.event.extendedProps.isMainEvent) { calendar.refetchEvents(); // 调整时长后,收尾时段自动延后 } } }); calendar.render(); });
4. 自定义渲染区分主时段与准备/收尾
用eventContent回调生成事件的HTML结构,给准备/收尾部分添加不可点击样式,视觉上区分不同时段:
eventContent: function(info) { if (!info.event.extendedProps.isMainEvent) { return { html: info.event.title }; } const { prepDuration, wrapupDuration } = info.event.extendedProps; const totalMinutes = (moment(info.event.end).diff(info.event.start, 'minutes') + prepDuration + wrapupDuration); // 计算各时段的宽度比例 const prepWidth = (prepDuration / totalMinutes) * 100; const mainWidth = (moment(info.event.end).diff(info.event.start, 'minutes') / totalMinutes) * 100; const wrapupWidth = (wrapupDuration / totalMinutes) * 100; return { html: ` <div class="event-box"> <div class="event-prep" style="width: ${prepWidth}%; pointer-events: none;">准备</div> <div class="event-main" style="width: ${mainWidth}%;">${info.event.title}</div> <div class="event-wrapup" style="width: ${wrapupWidth}%; pointer-events: none;">收尾</div> </div> ` }; }
5. 月视图隐藏准备/收尾时段
通过eventClassNames给主事件添加视图专属类,配合CSS在月视图下隐藏准备/收尾:
eventClassNames: function(arg) { if (arg.event.extendedProps.isMainEvent && arg.view.type === 'dayGridMonth') { return ['hide-prep-wrapup']; } return []; }
对应的CSS:
.hide-prep-wrapup .event-prep, .hide-prep-wrapup .event-wrapup { display: none; } .hide-prep-wrapup .event-main { width: 100% !important; }
方案优势
- 无需创建独立事件,避免
groupId关联失效和删除重建的性能损耗 - 依托FullCalendar原生机制处理重叠和同步,逻辑更稳定
- 自定义渲染直接在主事件内区分时段,无独立事件的同步偏差问题
内容的提问来源于stack exchange,提问作者Anchar
相关产品推荐
相关产品推荐

