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

FullCalendar.js+PHP+MySQL:按会议室颜色设置事件背景色失败

FullCalendar事件背景色无法按会议室ID匹配问题

我想根据MySQL数据库中3个会议室的room_id,给FullCalendar的事件设置对应背景色,但目前所有事件都显示为绿色(#179f66),未达到预期效果。

我已通过resources.php为会议室分配对应颜色,在script.js中尝试过事件初始化时设置backgroundColor、borderColor,也使用过eventDidMount钩子,但均无效;修改eventDidMount后仅改变了事件的点颜色。相关代码及问题截图如下:

问题截图

初始状态(所有事件为绿色):
所有事件显示绿色

修改eventDidMount后(仅事件点颜色改变):
仅事件点颜色改变

相关代码

resources.php

$sql = "SELECT id, room_name AS title FROM room_list";
$stmt = $conn->prepare($sql);
$stmt->execute();
$result = $stmt->get_result();

$colors = ['#00DCFF', '#fe9e0c', '#179f66'];
$colorIndex = 0;

$resources = array();
if ($result->num_rows > 0) {
  while ($row = $result->fetch_assoc()) {
    $row['color'] = $colors[$colorIndex % count($colors)];
    $resources[] = $row;
    $colorIndex++;
  }
}

echo json_encode($resources);

$stmt->close();

初始script.js

document.addEventListener("DOMContentLoaded", function () {
  $.ajax({
    url: "models/resources.php",
    type: "GET",
    dataType: "json",
    success: function (resources) {
      initializeCalendar(resources);
    },
  });
});

function initializeCalendar(resources) {
  let events = [];
  if (scheds) {
    Object.keys(scheds).map((k) => {
      let row = scheds[k];
      let room = resources.find((resource) => resource.id == row.room_id);
      let color = room.color;
      let event = {
        id: row.id,
        title: row.title,
        start: row.start_datetime,
        end: row.end_datetime,
        resourceId: row.room_id,
        backgroundColor: color,
        borderColor: color,
      };
      
      events.push(event);
    });
  }
  let calendarEl = document.getElementById("calendar");
  let calendar = new FullCalendar.Calendar(calendarEl, {
    schedulerLicenseKey: "CC-Attribution-NonCommercial-NoDerivatives",
    headerToolbar: {
      left: "prev,next,today",
      center: "title",
      right:
        "resourceTimeGridDay,resourceTimeGridFourDay,resourceTimeGridMonths",
    },
    views: {
      resourceTimeGridFourDay: {
        type: "resourceTimeGrid",
        duration: { days: 3 },
        buttonText: "3 Days",
      },
      resourceTimeGridMonths: {
        type: "dayGridMonth",
        duration: { months: 1 },
        buttonText: "Months",
      },
      resourceTimeGridDay: {
        buttonText: "Day",
      },
    },
    resources: resources,
    events: events,
    editable: true,
    allDaySlot: false,
    datesAboveResources: true,
    eventDidMount: function (info) {
      if (scheds) {
        Object.keys(scheds).map((k) => {
          let row = scheds[k];
          let room = resources.find((resource) => resource.id == row.room_id);
          let color = room.color;
          info.el.style.backgroundColor = color;
        });
      }
    },
  });

  calendar.render();
}

修改后的eventDidMount代码

eventDidMount: function (info) {
      if (scheds) {
        Object.keys(scheds).map((k) => {
          let row = scheds[k];
          let room = resources.find((resource) => resource.id == row.room_id);
          let color = room.color;
          info.event.extendedProps.backgroundColor = color;
        });
      }
    },

问题分析与解决方法

核心问题

  1. ID类型不匹配:resources中的id(数据库查询返回可能为字符串)与scheds里的room_id(可能为数字)类型不一致,导致resources.find()无法正确匹配,最终始终取到最后一个房间的绿色;
  2. eventDidMount循环逻辑错误:遍历所有scheds给当前事件设置颜色,导致所有事件被覆盖为最后一个房间的颜色;且修改extendedProps.backgroundColor不会直接触发DOM样式更新;
  3. TimeGrid视图样式层级:该视图下事件的背景色由内部.fc-event-main元素控制,直接修改info.el可能不生效。

修复方案

1. 统一ID匹配逻辑

在查找对应会议室时,强制转换类型确保匹配:

let room = resources.find((resource) => String(resource.id) === String(row.room_id));

2. 修正eventDidMount逻辑

无需遍历所有日程,直接通过当前事件的resourceId匹配会议室,修改正确的DOM元素:

eventDidMount: function (info) {
  // 通过当前事件关联的resourceId找到对应会议室
  let room = resources.find((resource) => String(resource.id) === String(info.event.resourceId));
  if (room) {
    // 修改事件外层元素的背景和边框
    info.el.style.backgroundColor = room.color;
    info.el.style.borderColor = room.color;
    // 针对TimeGrid视图,修改内部核心元素的背景色
    const eventMain = info.el.querySelector('.fc-event-main');
    if (eventMain) {
      eventMain.style.backgroundColor = room.color;
    }
  }
},

3. 简化事件初始化代码

用Object.values()替代Object.keys()遍历,减少冗余代码:

function initializeCalendar(resources) {
  let events = [];
  if (scheds) {
    events = Object.values(scheds).map(row => {
      let room = resources.find((resource) => String(resource.id) === String(row.room_id));
      // 找不到对应会议室时用默认色
      let color = room ? room.color : '#179f66';
      return {
        id: row.id,
        title: row.title,
        start: row.start_datetime,
        end: row.end_datetime,
        resourceId: row.room_id,
        backgroundColor: color,
        borderColor: color
      };
    });
  }
  // 后续日历初始化代码保持不变
}

4. 更便捷的自动着色方案

在resources.php中将颜色字段改为eventColor,FullCalendar会自动将该颜色应用到对应资源下的所有事件,无需手动设置:

// resources.php中修改颜色字段名
$row['eventColor'] = $colors[$colorIndex % count($colors)];

这样只要事件正确设置resourceId,就会自动继承对应会议室的颜色,省去手动配置颜色的步骤。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:32:21