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

FullCalendar动态时段时长设置问题:时段选择时间不匹配

问题

我们使用FullCalendar实现排球场预订功能,预订时段为10:00-23:00。需求为:10:00-15:00(原表述03:00应为笔误,实际为下午3点)设置1小时的时段时长,15:00-23:00设置1.5小时的时段时长,以对应不同定价,但目前无法实现该配置。

当前问题:使用select范围钩子时,出现开始时间与结束时间不匹配的情况,导致无法创建事件。例如点击19:00-20:30的时段,select返回的却是18:00-19:00,与实际选择不符。

附当前Calendar组件配置代码:

<Calendar
  schedulerLicenseKey="CC-Attribution-NonCommercial-NoDerivatives"
  initialView={view}
  dayMaxEventRows={3}
  snapDuration="01:00:00"
  slotLabelFormat={{ month:"long"}}
  defaultRangeSeparator="to"
  select={onSelectRange}
  aspectRatio={3}
  datesSet={handleDatesSet} // Set custom keys when dates are set
  dateClick={handleDateClick} // Handle click on dates
  longPressDelay={1}
  resourceAreaWidth={smUp?150:100}
  height={smUp?dummyResources.length*65:dummyResources.length*60}
  showNonCurrentDates={false}
  selectMirror
  slotMinutes= {5}
  eventDrop={arg => {
    onDropEvent(arg, updateEvent);
  }}
  eventResize={arg => {
    onResizeEvent(arg, updateEvent);
  }}
  slotDuration="01:00:00"
  slotMinTime="10:00:00"
  slotMaxTime="23:00:00"
  slotLabelContent={arg=>slotGenerator.next().value?.time}
  viewDidMount={arg => {
    console.log(arg.view.calendar,'mew------------------------------------------------')
  }}
  resourcesInitiallyExpanded
  initialResources={dummyResources}
  resourceLabelContent={({ resource }) => resource.title}
  plugins={[
    listPlugin,
    dayGridPlugin,
    timelinePlugin,
    timeGridPlugin,
    resourceTimelinePlugin,
    resourceTimeGridPlugin,
    interactionPlugin,
  ]}
/>
解决方案

一、修复select时间不匹配问题

当前配置里的snapDuration="01:00:00"会强制将选择时间对齐到1小时间隔,这就是点击19:00-20:30却返回18:00-19:00的核心原因。

  • 直接删除snapDuration="01:00:00"配置,让选择时间完全跟随用户点击范围。
  • 后续结合分时段逻辑调整slotDuration相关配置。

二、实现分时段时长配置

FullCalendar没有原生支持分时段设置不同slotDuration的功能,需通过自定义逻辑实现:

1. 自定义选择范围修正

在onSelectRange钩子中,根据开始时间所属时段自动调整结束时间,确保符合时长规则:

const onSelectRange = (info) => {
  let start = info.start;
  let end = info.end;
  const startHour = start.getHours();

  // 10:00-15:00 强制1小时时长
  if (startHour >= 10 && startHour < 15) {
    // 对齐开始时间到整点,结束时间+1小时
    const alignedStart = new Date(start.setMinutes(0, 0, 0));
    const alignedEnd = new Date(alignedStart.getTime() + 60 * 60 * 1000);
    // 若结束时间超过15:00则截断
    if (alignedEnd.getHours() > 15) {
      alignedEnd.setHours(15, 0, 0, 0);
    }
    // 使用修正后的时间创建事件
    createEvent(alignedStart, alignedEnd);
  } 
  // 15:00-23:00 强制1.5小时时长
  else if (startHour >=15 && startHour <23) {
    // 对齐开始时间到最近的整点/半点
    const minutes = start.getMinutes();
    const alignedMinutes = minutes <30 ? 0 :30;
    const alignedStart = new Date(start.setMinutes(alignedMinutes, 0, 0));
    const alignedEnd = new Date(alignedStart.getTime() + 90 *60 *1000);
    // 若结束时间超过23:00则截断
    if (alignedEnd.getHours() >23) {
      alignedEnd.setHours(23,0,0,0);
    }
    createEvent(alignedStart, alignedEnd);
  }
};

2. 限制合法选择范围

添加selectAllow回调,直接禁止不符合时长规则的选择操作:

selectAllow={(info) => {
  const start = info.start;
  const end = info.end;
  const duration = (end - start) / (1000 *60);
  const startHour = start.getHours();

  if (startHour >=10 && startHour <15) {
    // 仅允许1小时范围且不超过15:00
    return duration ===60 && end.getHours() <=15;
  } else if (startHour >=15 && startHour <23) {
    // 仅允许90分钟范围且不超过23:00
    return duration ===90 && end.getHours() <=23;
  }
  return false;
}}

3. 自定义槽位显示(可选)

如果需要在日历上直观区分不同时段,可修改slotLabelContent添加标识:

slotLabelContent={arg => {
  const hour = arg.date.getHours();
  if (hour >=10 && hour <15) {
    return <span>{arg.date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})} (1小时时段)</span>;
  } else if (hour >=15 && hour <23) {
    return <span>{arg.date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})} (1.5小时时段)</span>;
  }
  return '';
}}

三、最终配置调整要点

  • 移除snapDuration配置,避免强制时间对齐。
  • 保留slotMinTime="10:00:00"和slotMaxTime="23:00:00"限制可预订时段。
  • 添加selectAllow回调控制合法选择范围。
  • 在onSelectRange中完成时间规则修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:43:09