You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让fullCalendar Scheduler按拖拽位置渲染事件而非固定在末尾

解决fullCalendar Scheduler拖拽外部事件到已有事件之间的渲染问题

我之前在用fullCalendar Scheduler做拖拽功能时,也碰到过一模一样的问题——外部事件拖过去后总跑到日历末尾,没法精准插入到两个已有事件之间。核心问题其实是drop回调里没正确计算新事件的时间位置,也没利用好日历按时间排序渲染事件的逻辑。

你可以试试这样修改你的drop代码:

drop: function(date, jsEvent, ui, resourceId) {
  console.log("dropped");
  // 先拿到拖拽的外部事件基础数据
  const draggedEventEl = $(ui.draggable);
  const eventTitle = draggedEventEl.text();
  const eventId = draggedEventEl.attr('id');
  
  // 获取当前日历实例,方便后续操作
  const calendar = $('#your-calendar-id').fullCalendar('getCalendar');
  // 筛选出当前资源下的所有已有事件
  const targetResourceEvents = calendar.getEvents().filter(evt => evt.resourceId === resourceId);
  
  // 把已有事件按开始时间升序排序,方便找到插入位置
  targetResourceEvents.sort((a, b) => a.start.unix() - b.start.unix());
  
  // 确定新事件应该插入的位置索引
  let insertIndex = targetResourceEvents.length; // 默认插在最后
  for (let i = 0; i < targetResourceEvents.length; i++) {
    const currentEvt = targetResourceEvents[i];
    // 如果拖拽时间点在当前事件之前,插在当前事件前面
    if (date.isBefore(currentEvt.start)) {
      insertIndex = i;
      break;
    }
    // 如果拖拽时间点在当前事件和下一个事件之间,插在中间
    if (i < targetResourceEvents.length - 1) {
      const nextEvt = targetResourceEvents[i+1];
      if (date.isAfter(currentEvt.end) && date.isBefore(nextEvt.start)) {
        insertIndex = i + 1;
        break;
      }
    }
  }
  
  // 定义新事件的时长(你可以根据需求调整,比如从外部事件取预设时长)
  const eventDuration = moment.duration(1, 'hour');
  let eventStart = date.clone();
  let eventEnd = date.clone().add(eventDuration);
  
  // 处理和前后事件的重叠问题(如果不允许重叠的话)
  if (insertIndex > 0) {
    const prevEvt = targetResourceEvents[insertIndex - 1];
    if (eventStart.isBefore(prevEvt.end)) {
      eventStart = prevEvt.end.clone();
      eventEnd = eventStart.clone().add(eventDuration);
    }
  }
  if (insertIndex < targetResourceEvents.length) {
    const nextEvt = targetResourceEvents[insertIndex];
    if (eventEnd.isAfter(nextEvt.start)) {
      eventEnd = nextEvt.start.clone();
      eventStart = eventEnd.clone().subtract(eventDuration);
    }
  }
  
  // 添加新事件到日历
  calendar.addEvent({
    id: eventId,
    title: eventTitle,
    start: eventStart,
    end: eventEnd,
    resourceId: resourceId,
    className: draggedEventEl.attr('class') // 继承原事件的样式
  });
  
  // 可选:拖拽完成后移除页面上的原外部事件元素
  draggedEventEl.remove();
}

关键注意点:

  • 获取并排序目标资源的事件:只有把已有事件按时间排序,才能准确找到新事件的插入位置,保证渲染顺序正确。
  • 精准计算事件的起止时间:fullCalendar的资源视图是按事件的start时间自动排序渲染的,只要新事件的start时间落在两个已有事件的时间区间内,就会自动显示在中间位置。如果允许事件重叠,可以去掉重叠检查的代码块。
  • 确保日历配置正确:别忘了在日历初始化时开启droppable: true,并设置dropAccept指定可拖拽的元素类名,比如:
$('#your-calendar-id').fullCalendar({
  schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
  resources: [/* 你的资源数据 */],
  defaultView: 'timelineResourceDay', // 或者你使用的其他资源视图
  editable: true,
  droppable: true,
  dropAccept: '.fc-event',
  // 其他配置项...
});

这样调整后,拖拽外部事件到两个已有事件之间时,新事件就会显示在对应的位置,而不是默认跑到末尾啦。

内容的提问来源于stack exchange,提问作者Jack1999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:48:45