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

React中FullCalendar Resource Timeline View问题:跨视图事件不显示、事件添加无响应及插槽颜色点击切换需求实现

解决FullCalendar Resource Timeline视图的三大问题及预订日历实现

Hey there! Let's break down your issues and build that custom booking calendar you need, step by step.

1. 跨视图事件显示异常:普通视图事件在Resource Timeline不显示

问题根源

Resource Timeline视图是按资源分组渲染的,只有携带resourceId属性的事件才能匹配到对应的资源列。而你在dayGridMonth、timeGridWeek视图添加事件时,代码没有给事件分配resourceId,导致这些事件无法在资源视图中找到对应列,自然看不到。

修复方案

修改handleDateSelect函数,自动获取当前选中的资源ID(仅在Resource视图下存在),并给事件添加resourceId属性。同时,确保初始化事件INITIAL_EVENTS也包含resourceId:

const handleDateSelect = (selectInfo) => {
  let title = prompt('Please enter a new title for your event')
  let calendarApi = selectInfo.view.calendar
  calendarApi.unselect() // 清空日期选中状态

  if (title) {
    // 获取当前选中的资源ID(Resource视图下才有这个属性)
    const resourceId = selectInfo.resource?.id;
    calendarApi.addEvent({
      id: createEventId(),
      title,
      start: selectInfo.startStr,
      end: selectInfo.endStr,
      allDay: selectInfo.allDay,
      // 仅在Resource视图下添加resourceId,不影响普通视图显示
      ...(resourceId && { resourceId })
    })
  }
}

同时,更新你的初始化事件数组:

const INITIAL_EVENTS = [
  {
    id: '1',
    title: 'Sample Booking',
    start: '2024-05-20',
    end: '2024-05-21',
    allDay: true,
    resourceId: 'a' // 关联到资源a
  }
]

2. 自定义视图customWeeks添加事件无响应

问题根源

你的FullCalendar配置里有一行错误的events设置:events={{ display: 'background' }}。这行代码会覆盖initialEvents的配置,且不符合FullCalendar的事件格式要求(events应接收数组、函数或URL,而非这种对象),导致事件添加后无法被正确渲染。

修复方案

直接删除这行错误配置,保留initialEvents即可:

<FullCalendar
  plugins={[interactionPlugin, resourceTimelinePlugin, dayGridPlugin, timeGridPlugin]}
  headerToolbar={{ left: 'prev', center: 'title', right: 'next,customWeeks,dayGridMonth,timeGridWeek,resourceTimelineWeek' }}
  initialView='customWeeks'
  views={{
    customWeeks:{
      type: 'resourceTimeline',
      duration: { weeks: 2 },
      slotDuration: {days: 1},
      buttonText: 'Custom Week'
    }
  }}
  // 移除错误的events={{ display: 'background' }}配置
  resourceAreaWidth='80px'
  weekNumbers={true}
  resourceAreaHeaderContent=' '
  // ...其余配置保持不变
/>

结合第一个问题的修复,添加事件时携带resourceId,customWeeks视图就能正常显示新添加的事件了。

3. 核心需求:CustomWeeks视图插槽点击切换颜色(预订日历效果)

要实现插槽初始颜色+点击切换的效果,我们可以通过维护预订状态集合,结合slotRender钩子渲染背景色,再通过点击事件更新状态。

实现步骤

  1. 添加状态记录已预订的插槽(用resourceId + 日期字符串作为唯一标识):
const [bookedSlots, setBookedSlots] = useState(new Set());
  1. 编写slotRender函数,根据预订状态设置插槽背景色:
const handleSlotRender = (slotInfo) => {
  // 生成插槽唯一标识:resourceId + 日期(YYYY-MM-DD)
  const slotKey = `${slotInfo.resource.id}-${slotInfo.startStr.split('T')[0]}`;
  // 设置初始颜色和预订后颜色
  slotInfo.el.style.backgroundColor = bookedSlots.has(slotKey) ? '#ffcccc' : '#e8f4f8';
  // 给插槽绑定点击切换事件
  slotInfo.el.addEventListener('click', () => {
    toggleSlotBooking(slotKey);
  });
};

// 切换预订状态的函数
const toggleSlotBooking = (slotKey) => {
  setBookedSlots(prev => {
    const newSet = new Set(prev);
    newSet.has(slotKey) ? newSet.delete(slotKey) : newSet.add(slotKey);
    return newSet;
  });
};
  1. 在FullCalendar组件中添加slotRender配置,同时可按需调整select事件(区分添加事件和切换预订):
<FullCalendar
  // ...其余配置
  slotRender={handleSlotRender}
  // 可选:区分添加事件和切换预订的操作
  select={(selectInfo) => {
    const action = prompt('Choose action:\n1 = Add Event\n2 = Toggle Booking');
    if (action === '1') {
      handleDateSelect(selectInfo);
    } else if (action === '2') {
      const slotKey = `${selectInfo.resource.id}-${selectInfo.startStr.split('T')[0]}`;
      toggleSlotBooking(slotKey);
      selectInfo.view.calendar.unselect();
    }
  }}
/>

优化小贴士

  • 可以把颜色提取成CSS变量,方便统一维护:
.seats-calendar .fc-slot {
  --default-slot: #e8f4f8;
  --booked-slot: #ffcccc;
  background-color: var(--default-slot);
}

然后在slotRender中修改CSS变量:

slotInfo.el.style.setProperty('--default-slot', bookedSlots.has(slotKey) ? '#ffcccc' : '#e8f4f8');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 12:52:34