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; }); } },
问题分析与解决方法
核心问题
- ID类型不匹配:
resources中的id(数据库查询返回可能为字符串)与scheds里的room_id(可能为数字)类型不一致,导致resources.find()无法正确匹配,最终始终取到最后一个房间的绿色; - eventDidMount循环逻辑错误:遍历所有
scheds给当前事件设置颜色,导致所有事件被覆盖为最后一个房间的颜色;且修改extendedProps.backgroundColor不会直接触发DOM样式更新; - 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
相关产品推荐
相关产品推荐

