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

React FullCalendar:支持用户通过拖拽调整日历事件的上下排序

实现FullCalendar DayGridMonth视图内事件拖拽排序

核心思路

通过FullCalendar的拖拽交互API,结合自定义排序逻辑,在拖拽结束后更新事件的优先级字段,重新排序并渲染对应日期的事件,实现单元格内直接拖拽调整顺序的效果。


1. 基础配置(启用拖拽)

初始化FullCalendar时开启编辑/拖拽功能,同时引入interaction插件支持拖拽交互:

document.addEventListener('DOMContentLoaded', function() {
  const calendarEl = document.getElementById('calendar');
  const calendar = new FullCalendar.Calendar(calendarEl, {
    plugins: ['dayGrid', 'interaction'],
    initialView: 'dayGridMonth',
    editable: true, // 全局开启编辑拖拽
    eventDragStop: handleEventReorder, // 绑定拖拽结束事件
    events: [
      // 示例事件:需包含start(日期)、priority(排序字段)
      { title: '任务A', start: '2024-05-20', priority: 1, id: 'evt1' },
      { title: '任务B', start: '2024-05-20', priority: 2, id: 'evt2' }
    ]
  });
  calendar.render();
});

2. 拖拽排序逻辑实现

定义拖拽结束后的处理函数,根据拖拽方向调整事件优先级,重新排序对应日期的事件:

function handleEventReorder(info) {
  const draggedEvent = info.event;
  const targetDate = draggedEvent.startStr;
  // 获取当前日期下的所有事件
  const dayEvents = calendar.getEvents().filter(evt => evt.startStr === targetDate);
  const draggedIndex = dayEvents.findIndex(evt => evt.id === draggedEvent.id);

  let newPriority;
  // 根据拖拽方向计算新优先级(从上到下优先级数值递增)
  if (info.deltaY > 0) {
    // 向下拖拽:取后一个事件优先级+1,无后续则取当前最大优先级+1
    const nextEvent = dayEvents[draggedIndex + 1];
    newPriority = nextEvent ? nextEvent.extendedProps.priority + 1 : Math.max(...dayEvents.map(e => e.extendedProps.priority)) + 1;
  } else {
    // 向上拖拽:取前一个事件优先级-1,无前驱则取当前最小优先级-1
    const prevEvent = dayEvents[draggedIndex - 1];
    newPriority = prevEvent ? prevEvent.extendedProps.priority - 1 : Math.min(...dayEvents.map(e => e.extendedProps.priority)) - 1;
  }

  // 更新当前事件优先级
  draggedEvent.setExtendedProp('priority', newPriority);
  
  // 重新排序并渲染当前日期的事件
  dayEvents.sort((a, b) => a.extendedProps.priority - b.extendedProps.priority);
  calendar.removeEvents(evt => evt.startStr === targetDate);
  calendar.addEventSource(dayEvents);

  // 可选:将新的优先级数据提交到后端保存
  // saveEventPriority(draggedEvent.id, newPriority);
}

3. 初始渲染时按优先级排序

确保页面加载时,每个日期的事件默认按优先级排序展示:

// 对原始事件数据按日期分组后排序
function sortEventsByPriority(events) {
  const groupedByDate = {};
  events.forEach(evt => {
    const date = evt.start;
    if (!groupedByDate[date]) groupedByDate[date] = [];
    groupedByDate[date].push(evt);
  });
  // 每组按优先级升序排列
  Object.values(groupedByDate).forEach(group => {
    group.sort((a, b) => a.priority - b.priority);
  });
  // 扁平化后返回
  return [].concat(...Object.values(groupedByDate));
}

// 使用示例
const rawEvents = [/* 你的原始事件数组 */];
const sortedEvents = sortEventsByPriority(rawEvents);
calendar.addEventSource(sortedEvents);

注意事项

  • 如果需要支持跨日期拖拽,需在handleEventReorder中额外处理事件的start字段更新逻辑。
  • 若要持久化排序结果,在更新优先级后需调用后端接口保存最新的优先级数据。
  • 可优化优先级计算逻辑,比如直接使用拖拽后的索引作为优先级(如索引0对应优先级1,索引1对应优先级2),避免出现数值间隙。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 19:32:24