循环事件
循环事件是日历应用程序中的一个实用功能,允许用户设置按指定间隔重复的事件。从 7.1 版本开始,Scheduler 采用了 RFC-5545 标准格式来支持循环事件。
本指南将介绍如何在 Scheduler 中使用循环事件,以及如何将其保存到数据库中。
您可以在这里查看旧版循环事件格式的说明。
默认情况下,Scheduler 并未启用循环事件。要添加此功能,您需要在页面上激活一个特殊扩展 -- recurring 插件:
scheduler.plugins({
recurring: true
});
启用循环事件后,lightbox 界面将会多出一个额外的部分,如下图所示:

配置选项
该库为循环事件提供了以下配置选项:
- repeat_date - 控制 'recurring' lightbox 中"结束日期"字段所使用的日期格式。
scheduler.config.repeat_date = "%m/%d/%Y";
...
scheduler.init('scheduler_here', new Date(2019, 7, 5), "month");
'Recurring' lightbox
启用 recurring 扩展后,lightbox 会增加一个名为"Repeat event"的部分。'recurring' lightbox 的默认配置如下:
[
{name:"description", height:130, map_to:"text", type:"textarea" , focus:true},
{name:"recurring", height:115, type:"recurring", map_to:"rec_type",
button:"recurring"},
{name:"time", height:72, type:"time", map_to:"auto"}
];
您可以自由添加其他部分,但请确保"recurring"和"time"这两个部分必须保留。同时,"time"部分应始终放在"recurring"部分之后。
格式说明
循环事件在数据库中以单条记录的形式保存,该记录包含所有标准事件字段以及一些额外属性:
- start_date - (datetime) 表示系列的起始日期
- end_date - (datetime) 表示系列的结束日期
- rrule - (string) 定义循环规则
- duration - (number) 每次循环实例的持续时间
- recurring_event_id - (string|number) 父系列的 ID,仅在修改或删除实例时设置
- original_start - (datetime) 被编辑实例的原始日期,仅在修改或删除实例时设置
- deleted - (boolean) 标记为已删除的实例,仅在删除实例时设置
rrule 属性遵循 RFC-5545 中定义的 iCalendar 格式,用于指定频率、间隔及其他循环细节。
与 iCalendar 格式的区别
我们的格式与 iCalendar 格式有两点主要不同:
STDATE 和 DTEND 的单独存储
iCalendar 通常将循环系列的起止日期作为 STDATE 和 DTEND 属性包含在 RRULE 字符串中,而我们的格式则将 start_date 和 end_date 作为单独字段存储。这样可以更方便地按日期处理和查询循环事件,而无需解析 RRULE 字符串。
以下是一个每周一重复、从 2024 年 6 月 1 日至 2024 年 12 月 1 日的循环事件系列示例:
{
"id": 1,
"text": "Weekly Team Meeting",
"start_date": "2024-06-03 09:00:00",
"duration": 3600,
"end_date": "2024-12-02 10:00:00",
"rrule": "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO",
"recurring_event_id": null,
"original_start": null
}
异常情况的处理
异常情况(即被修改或删除的实例)会作为单独的事件记录存储,并与其父系列关联。这些异常记录包含三个额外属性:recurring_event_id、original_start 和 deleted。它们用于标识哪些实例已被更改或移除,以及它们与主系列的关系。
与标准 iCalendar 格式不同,异常(被修改或删除的实例)不会存储在 RRULE 的 EXDATE 属性中。
以下是一个包含一个被修改和一个被删除实例的循环系列示例:
[
{
"id": 1,
"text": "Weekly Team Meeting",
"start_date": "2024-06-03 09:00:00",
"duration": 3600,
"end_date": "2024-12-02 10:00:00",
"rrule": "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO",
"recurring_event_id": null,
"original_start": null
},
{
"id": 2,
"text": "Special Team Meeting",
"start_date": "2024-06-10 09:00:00",
"end_date": "2024-06-10 11:00:00",
"rrule": null,
"recurring_event_id": 1,
"original_start": "2024-06-10 09:00:00"
},
{
"id": 3,
"text": "Deleted Team Meeting",
"start_date": "2024-06-17 09:00:00",
"end_date": "2024-06-17 10:00:00",
"rrule": null,
"recurring_event_id": 1,
"original_start": "2024-06-17 09:00:00",
"deleted": true
}
]
原定于 2024-06-10 09:00:00 的事件已被 Special Team Meeting 记录所替代,而 2024-06-17 09:00:00 的事件则被省略。
请注意,已修改或删除实例的 rrule 属性会被忽略。
同时,被删除实例的 text、start_date 和 end_date 字段不会影响 Scheduler 的行为。
编辑/删除系列中的某一实例
您可以删除或编辑循环系列中的某一具体实例。
重要提示
- 对循环事件的每一次更改都会在数据库中生成一条新记录。
- 单个实例通过 recurring_event_id 属性与主系列关联。
- 当某一实例被编辑时,original_start 字段保存的是该实例最初计划的日期,而不是新日期。例如,如果原定于 2024 年 7 月 27 日 15:00 的实例被移动到 2024 年 7 月 30 日 15:00,original_start 仍为 2024 年 7 月 27 日 15:00。
服务端逻辑
除了额外字段外,服务端控制器还应实现以下逻辑:
- 当添加已删除的实例时,服务端响应必须包含 "deleted" 状态。
- 已删除实例通过非空的 deleted 属性识别。
- 当系列被修改时,所有与该系列关联的已修改和已删除实例都应被移除。
- 系列通过非空 rrule 且空 recurring_event_id 识别。
- 已修改实例为所有 recurring_event_id 与系列 id 匹配的记录。
- 如果删除了 recurring_event_id 非空的事件,应通过设置 deleted="true" 进行标记,而不是直接移除。
完整代码示例请参见这里
自定义 lightbox 的 recurring 区块控件
从 4.2 版本开始,dhtmlxScheduler 允许您为 lightbox 的 'recurring' 部分自定义 HTML 表单。
可以自定义哪些内容?
- 更改表单的结构。
- 移除不需要的元素(如"每年"重复选项及其输入框)。
- 为输入项设置默认值(例如默认选中"无结束日期"并隐藏循环结束设置区块)。