feat(待办): 支持循环任务(标准 CalDAV / VTODO RRULE)#5
只按标准 CalDAV 实现,不依赖家书的自定义机制。 群晖等标准服务器:RRULE 写在 VTODO 上,由客户端负责展开。 ## 核心语义决策 循环待办「勾完成」= 这一轮做完了,推进到下一周期,而不是结束。 若照搬非循环逻辑(置 COMPLETED 就完结),用户每勾一次循环任务它就永久结束, 循环规则等于白设。所以: · 非循环 → 置 COMPLETED,永久结束 · 循环 → DUE 推到下一周期 + 状态复位 NEEDS-ACTION ## 关键修复:DTSTART 与 DUE 必须分开 原 parseTodos 把 DUE 和 DTSTART 都写进 startTime,后出现的覆盖先出现的。 但循环下两者语义完全不同: · DTSTART = RRULE 的重复基准 · DUE = 这一条的截止时间 混在一起会导致重复基准被截止时间覆盖,算出来的发生日全错。 现在拆成独立字段,数据库补 dtstart 列(rrule 列已有)。 ## 顺带修掉两个既有 bug(测试连带查出) rewriteTodoCompletion 与 rewriteTodoFields 里,插入阶段的块序号 vtodoIdx 在遇到 END:VTODO 时被重置成 -1 ⇒ 每块都从 0 重新数, 多 VTODO 文件里永远匹配不到目标块,字段加不上(静默失败, 表现为「点了没反应」)。三处一并修正,vtodoIdx 改为全局块序号。 ## 实现 - IcsUtil.incForFreq:按 FREQ 推周期,处理月末溢出 (1/31 + 1月 → 2/28 钳制,不跳到 3 月;2/29 + 1年 → 2/28) - IcsUtil.freqOfRrule / rewriteTodoRecurrence - TodoService.setRecurrence / completeRecurringRound - 写回时同时给 DTSTART + DUE:RFC 5545 里 VTODO 的 DTSTART 是 OPTIONAL, 但缺它时各客户端对 RRULE 基准理解不一致,显式给能消除歧义 - 待办行显示「↻ 每周」标记(否则循环任务和普通待办长得一样, 用户勾完发现「又冒出新的」会困惑) - 编辑弹框加 每天/每周/每月/每年 选择,再点一次取消 ## 验证 scripts/test-ics-todo-recurrence.js:24 项全通过 (月末钳制、闰年、字段保留、取消循环、多 VTODO 定位、结构完整性)。 编译 BUILD SUCCESSFUL。 ## 说明 服务器若不支持 RRULE(如群晖 Calendar 规格里未提及循环任务), 则循环只在客户端可见,同步到其它客户端会退化为普通任务。
This commit is contained in:
@@ -25,6 +25,11 @@ export class DisplayEvent {
|
||||
color: string = '#007DFF';
|
||||
completed: boolean = false; // 仅待办使用
|
||||
recurring: boolean = false; // 是否为重复日程展开出的发生
|
||||
/** ⭐ 待办的 RRULE 原文(空 = 非循环)。与 recurring 不同:
|
||||
* recurring 只说"重不重复",这里带的是"多久重复一次"。 */
|
||||
recurRule: string = '';
|
||||
/** 待办的 DTSTART(重复基准,毫秒;0 = 无) */
|
||||
dtstart: number = 0;
|
||||
writable: boolean = true; // 所属日历本是否可写(只读时点击显示详情而非编辑)
|
||||
}
|
||||
|
||||
@@ -365,6 +370,9 @@ export class CalendarDataService {
|
||||
d.calName = nameOf(e.calKey);
|
||||
d.color = colorOf(e.calKey);
|
||||
d.completed = e.completed;
|
||||
d.recurRule = e.rrule;
|
||||
d.dtstart = e.dtstart;
|
||||
d.recurring = e.rrule !== '';
|
||||
result.push(d);
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user