与 DHTMLX Scheduler 集成
本指南介绍如何将 DHTMLX Booking 组件与 DHTMLX Scheduler 集成。该集成在服务器端将 Scheduler 事件转换为 Booking 时间槽。
了解核心概念
集成的核心在于将 Scheduler 事件转换为 Booking 时间槽。开始之前,请注意以下几点。
Scheduler 事件与 Booking 时间槽。 Scheduler 处理事件,包括单次事件和循环事件。Booking 根据这些事件生成可用时间槽。下方示例 通过在服务器端转换 JSON 数据,从医生的日程中生成预约时间槽。
循环事件的限制。 Booking 仅支持每周循环事件,即 Scheduler 中定义为 INTERVAL=1;FREQ=WEEKLY 的事件。Scheduler 支持任意循环模式,因此请在 Scheduler 配置中限制其他循环选项。
时区处理。 Booking 以本地时区解析时间戳。如果使用全局时间戳,请在发送给 Booking 之前将其转换为本地时区,并在保存前转换回 UTC。有关转换说明,请参阅将 UTC 数据转换为本地时区。
Booking 时间槽策略。 选择以下两种方式之一来构建日程:
slots和usedSlots— 构建日程并排除已预约的时间槽(本文介绍此策略)availableSlots— 显式列出可预约的时间槽,适用于无循环的事件
示例
下方示例通过将医生日程转换为预约时间槽来实现 Booking 与 Scheduler 的集成。该集成使用四个数据端点:
/doctors/worktime— Scheduler 数据(医生日程),包含循环事件和单次事件,是 Booking 时间槽的数据来源/units— 在服务器端根据worktime数据生成的最终 Booking 时间槽;参见后端示例/doctors/reservations— 辅助集合,用于在时间轴视图中展示usedSlots;保存来自 Booking 表单的已预约时间槽/doctors— 所有医生的姓名和 ID;同时为 Scheduler 和 Booking 组件提供医生信息
事件到时间槽的转换是集成的核心。下一节 描述具体的转换规则。
将 Scheduler 事件转换为 Booking 时间槽
以下规则介绍如何使用 JSON 数据从医生日程生成预约时间槽,转换在服务器端完成。所有示例均以 2025-03-13 至 2027-03-13 的下一周期日程为例。
规则 1:从单次事件创建时间槽
对于每个单次事件,将开始时间和结束时间转换为 Booking 时间槽。在 slots 数组中添加一条记录,并在 dates 数组中包含事件日期。
以下代码片段展示一个单次 Scheduler 事件:
{
"doctor_id": 1,
"start_date": "2025-03-18 02:00:00",
"end_date": "2025-03-18 06:00:00"
}
以下代码片段展示转换后的 Booking 时间槽:
{
"id": 1,
"slotSize": 20,
"slotGap": 5,
"slots": [
{
"from": "02:00",
"to": "06:00",
"dates": [
1742256000000 // 2025-03-18 00:00:00(时间戳)
]
}
]
}
规则 2:转换循环事件
将循环事件映射为每周模式。Scheduler 中循环事件的开始日期和结束日期必须与 Booking 的 start 和 end 日期一致。否则,需要为循环事件开始之前和之后的日期创建占位符(参见规则 7)。
以下代码片段展示一个每周工作日(周一至周五)重复的循环 Scheduler 事件:
{
"doctor_id": 1,
"start_date": "2025-03-13 09:00:00",
"end_date": "2027-03-13 00:00:00",
"rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR",
"duration": 28800
}
Booking 将每周日程 表示为单条规则,每个工作日的开始时间和结束时间相同。
以下代码片段展示转换后的 Booking 时间槽:
{
"id": 1,
"slotSize": 20,
"slotGap": 5,
"slots": [
{
"from": "09:00",
"to": "17:00",
"days": [1, 2, 3, 4, 5] // 周一至周五
}
]
}
规则 3:拆分跨天事件
Booking 在单天内生成时间槽。如果一个事件跨越两天(例如从晚上 8 点开始,到凌晨 4 点结束),需将其拆分为两个时间槽,每天各一个。
例如,一位医生从周六晚上开始、持续到周日早上的班次,需拆分为两条规则:一条对应周六,一条对应周日。
以下代码片段展示跨天的 Scheduler 事件:
{
"doctor_id": 2,
"start_date": "2025-03-13 20:00:00",
"end_date": "2027-03-13 00:00:00",
"rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=SA",
"duration": 28800
}
以下代码片段展示转换后的两个 Booking 时间槽,每天各一个:
{
"id": 2,
"slotSize": 45,
"slotGap": 5,
"slots": [
{
"from": "20:00",
"to": "24:10",
"days": [6] // 周六
},
{
"from": "00:10",
"to": "04:00",
"days": [0] // 周日
}
]
}
规则 4:向循环日程添加单次事件
当单次事件扩展了循环日程时,需同时为两者生成时间槽。将单次事件的日期添加到循环规则的 dates 数组中。
本示例合并了两个 Scheduler 事件:
- 循环事件 — 医生在工作日上午 9 点至下午 5 点的可用时间
- 单次事件 — 3 月 18 日和 19 日凌晨 2 点至 6 点的额外可用时间
以下代码片段展示两个 Scheduler 事件:
[
// 循环事件
{
"doctor_id": 1,
"start_date": "2025-03-13 09:00:00",
"end_date": "2027-03-13 00:00:00",
"rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR",
"duration": 28800
},
// 单次事件
{
"doctor_id": 1,
"start_date": "2025-03-18 02:00:00",
"end_date": "2025-03-18 06:00:00"
},
{
"doctor_id": 1,
"start_date": "2025-03-19 02:00:00",
"end_date": "2025-03-19 06:00:00"
}
]
Booking 将循环事件和单次事件合并为一条规则。单次事件的日期(3 月 18 日和 19 日)具有更高优先级,并加入循环规则的 dates 数组。有关优先级顺序,请参阅定义时间槽规则。
以下代码片段展示合并后的 Booking 时间槽:
{
"id": 1,
"slotSize": 20,
"slotGap": 20,
"slots": [
{
"from": "02:00",
"to": "06:00",
"dates": [
1742256000000, // 2025-03-18 00:00:00
1742342400000 // 2025-03-19 00:00:00
]
},
{
"from": "09:00",
"to": "17:00",
"days": [1, 2, 3, 4, 5],
"dates": [
1742256000000, // 2025-03-18 00:00:00
1742342400000 // 2025-03-19 00:00:00
]
}
]
}
规则 5:修改循环事件的单个实例
当循环事件的某个实例发生变更(例如某天的时间调整)时,生成一个包含更新时间的新时间槽。将该日期添加到 dates 数组,它将覆盖该日期对应的 days 数组。
以下代码片段展示循环事件及其修改后的实例:
[
{
"doctor_id": 1,
"start_date": "2025-03-13 09:00:00",
"end_date": "2027-03-13 00:00:00",
"rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR",
"duration": 28800
},
{
"doctor_id": 1,
"start_date": "2025-03-14 03:00:00",
"end_date": "2025-03-14 11:00:00",
"recurring_event_id": "1",
"original_start": "2025-03-14 09:00"
}
]
以下代码片段展示循环规则以及针对修改日期的覆盖规则:
{
"id": 1,
"slotSize": 20,
"slotGap": 5,
"slots": [
{
"from": "09:00",
"to": "17:00",
"days": [1, 2, 3, 4, 5]
},
{
"from": "03:00",
"to": "11:00",
"dates": [
1741910400000 // 2025-03-14 03:00:00(已修改)
]
}
]
}
规则 6:删除循环事件的单个实例
当删除循环事件的某个实例时,需在 Booking 规则中体现该删除操作。为被删除的日期创建一条时间间隔为空的规则,并使用 dates 属性——其优先级高于 days。
以下代码片段展示循环事件及其已删除的实例:
[
{
"doctor_id": 5,
"start_date": "2025-03-14 09:00:00",
"end_date": "2027-03-13 00:00:00",
"rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=TH,FR,SA,SU",
"duration": 28800
},
{
"doctor_id": 5,
"start_date": "2025-03-23 09:00:00",
"end_date": "2025-03-23 17:00:00",
"recurring_event_id": "15",
"original_start": "2025-03-23 09:00",
"deleted": true
}
]
以下代码片段展示循环规则以及用于移除已删除日期的空时间间隔:
{
"id": 5,
"slotSize":60,
"slotGap":10,
"slots":[
{
"from": "09:00",
"to": "17:00",
"days": [4, 5, 6, 0] // 周四至周日
},
{
"from": "00:00",
"to": "00:00",
"dates": [
1742688000000 // 2025-03-23 00:00:00(已删除的实例)
]
}
]
}
规则 7:处理在 Booking 开始日期之后才开始的事件
如果循环事件的开始日期晚于 Booking 的开始日期(默认为今天,本示例中为 2025-03-13),则需为事件开始之前的日期创建空时间间隔规则,以从循环中移除这些日期。
以下代码片段展示一个在 Booking 开始日期四天后才开始的循环事件:
{
"doctor_id": 5,
"start_date": "2025-03-17 09:00:00",
"end_date": "2027-03-13 00:00:00",
"rrule": "INTERVAL=1;FREQ=WEEKLY;BYDAY=SU,MO,TU,WE,TH,FR,SA",
"duration": 28800
}
以下代码片段展示循环规则以及事件开始前四天的空时间间隔:
{
"id": 5,
"slotSize":60,
"slotGap":10,
"slots": [
{ "from": "09:00", "to": "17:00", "days": [0, 1, 2, 3, 4, 5, 6] },
{ "from": "00:00", "to": "00:00", "dates": [
1741820400000, // 2025 年 3 月 13 日
1741906800000, // 2025 年 3 月 14 日
1741993200000, // 2025 年 3 月 15 日
1742079600000 // 2025 年 3 月 16 日
]}
]
}