FullCalendar资源时间线拖拽事件按优先级预览重排实现咨询
解决方案:FullCalendar资源时间线视图拖拽事件继承优先级预览
针对你在React+TypeScript技术栈下,使用FullCalendar资源时间线视图时遇到的拖拽事件继承优先级预览问题,以下是两种可行的实现方案:
方案一:基于事件监听+临时状态的轻量实现
核心思路是通过监听拖拽悬停事件获取目标事件的优先级,结合eventDragMutationMassagers修改拖拽事件的优先级,利用FullCalendar自带的eventOrder配置实现实时重排预览。
具体实现代码
import { useState } from 'react'; import FullCalendar from '@fullcalendar/react'; import resourceTimelinePlugin from '@fullcalendar/resource-timeline'; import type { EventDragOverArg, EventMutation } from '@fullcalendar/core'; const ScheduleCalendar = () => { // 维护当前悬停事件的优先级状态 const [hoveredTargetPriority, setHoveredTargetPriority] = useState<number | null>(null); // 监听拖拽悬停,检测是否命中其他事件 const handleEventDragOver = (info: EventDragOverArg) => { const hoveredEventEl = document.elementFromPoint(info.jsEvent.clientX, info.jsEvent.clientY); const targetEventEl = hoveredEventEl?.closest('.fc-event'); if (targetEventEl) { const targetEventId = targetEventEl.getAttribute('data-event-id'); const targetEvent = info.view.calendar.getEventById(targetEventId!); setHoveredTargetPriority(targetEvent?.extendedProps.priority || null); } else { setHoveredTargetPriority(null); } }; // 自定义拖拽事件的属性修改逻辑 const eventDragMutationMassagers = [ (mutation: EventMutation, context: any) => { if (hoveredTargetPriority !== null) { // 修改拖拽事件的优先级字段 mutation.eventMutations[0].extendedProps.priority = hoveredTargetPriority; } return mutation; } ]; return ( <FullCalendar plugins={[resourceTimelinePlugin]} initialView="resourceTimelineDay" // 配置按优先级排序,值越大事件越置顶 eventOrder="priority" allDayDefault={true} resources={[/* 你的员工资源数据 */]} events={[/* 你的事件数据,需包含extendedProps.priority字段 */]} eventDragOver={handleEventDragOver} eventDragMutationMassagers={eventDragMutationMassagers} // 拖拽结束后重置状态 eventDragStop={() => setHoveredTargetPriority(null)} /> ); }; export default ScheduleCalendar;
方案二:利用内部API强制触发Hit检测
如果需要更贴近FullCalendar原生拖拽逻辑,可以通过调用内部交互实例的方法,强制触发Hit生成,让eventDragMutationMassagers在悬停事件时生效。注意:该方案依赖内部未公开API,需锁定FullCalendar版本避免兼容性问题。
核心代码片段
import { useEffect, useRef } from 'react'; import FullCalendar from '@fullcalendar/react'; import resourceTimelinePlugin from '@fullcalendar/resource-timeline'; const ScheduleCalendar = () => { const calendarRef = useRef<any>(null); useEffect(() => { const calendarEl = document.querySelector('.fc'); if (!calendarEl || !calendarRef.current) return; const handleDragOver = (e: DragEvent) => { const targetEventEl = (e.target as HTMLElement).closest('.fc-event'); if (!targetEventEl) return; const targetEventId = targetEventEl.getAttribute('data-event-id'); const targetEvent = calendarRef.current.getEventById(targetEventId!); if (!targetEvent) return; // 手动构造Hit对象,模拟进入目标事件的资源和日期 const customHit = { resourceId: targetEvent.extendedProps.resourceId, date: targetEvent.start, event: targetEvent }; // 获取当前拖拽交互实例,强制更新Hit const dragInteraction = calendarRef.current.interactions.find( (inter: any) => inter.type === 'eventDrag' ); if (dragInteraction?.updateHit) { dragInteraction.updateHit(customHit); } }; calendarEl.addEventListener('dragover', handleDragOver); return () => calendarEl.removeEventListener('dragover', handleDragOver); }, []); // 在eventDragMutationMassagers中通过hit关联的事件获取优先级 const eventDragMutationMassagers = [ (mutation: any, context: any) => { const hitEvent = context.dragHit?.event; if (hitEvent) { mutation.eventMutations[0].extendedProps.priority = hitEvent.extendedProps.priority; } return mutation; } ]; return ( <FullCalendar ref={calendarRef} plugins={[resourceTimelinePlugin]} initialView="resourceTimelineDay" eventOrder="priority" allDayDefault={true} resources={[/* 你的员工资源数据 */]} events={[/* 你的事件数据 */]} eventDragMutationMassagers={eventDragMutationMassagers} /> ); }; export default ScheduleCalendar;
关键注意事项
- 确保事件数据中包含
extendedProps.priority字段,且eventOrder配置为"priority",这样修改优先级后视图会自动触发重排。 - 方案一不依赖内部API,兼容性更强;方案二需注意FullCalendar版本更新可能导致内部方法变更,建议锁定版本(如v6.x)。
- 拖拽结束后需重置临时状态,避免影响后续拖拽操作。
内容的提问来源于stack exchange,提问作者Matthew McDonald
相关产品推荐
相关产品推荐

