laoyang
|
788171d1b2
|
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 规格里未提及循环任务),
则循环只在客户端可见,同步到其它客户端会退化为普通任务。
|
2026-11-02 16:53:30 +08:00 |
|
laoyang
|
9066a12bbc
|
feat(待办): 按日历本分组 + 编辑/删除 + 修整行点击误完成 + 周视图圆点 #5 #6
## 1. 修 bug:整行点击都会勾选完成
上一版把 onClick 挂在最外层 Row 上,点标题/点截止时间/点空白都会改状态。
改为:
· 只有左侧圆圈 → 勾选/取消完成
· 其余内容区 → 打开编辑弹框(不改变完成状态)
## 2. 待办按日历本分组
用户:待办应按日历本分类,未完成里也能按家庭/生活分开,要有区分度。
未完成/已完成 两大段内部,再按日历本聚合:
· 分组标题前带该本颜色圆点(这是区分度的来源)
· 组标题显示 本名(数量)
· 组内按截止时间升序,无截止时间排最后
· 组之间按组内最早截止时间排序(最紧急的本在前)
CalendarDataService.loadTodos 补 d.calName(原来只带 calKey,分组标题没名字)。
## 3. 待办编辑弹框
点内容区弹出,可改:标题 / 备注 / 截止时间(含日期+时间选择器,可清除),
另有删除(二次确认)。只读本禁用编辑并提示。
⚠️ 用**整页覆盖层**而不是 bindSheet:ArkUI 同一组件只能挂一个 bindSheet,
Index 已用 detailShow 挂了日程详情,再挂会被覆盖(EventEditPage 顶部记过此坑)。
写入仍走「GET 原文 → 改字段 → PUT」,只动 SUMMARY/DESCRIPTION/DUE,
**不动 STATUS/COMPLETED**(改内容不该重置完成状态),
并保留 PRIORITY/CATEGORIES/X-* 等本地没存的字段。
## 4. 周视图圆点
weekStripDays 原来没算 hasEvent;补上与月视图**共用同一份**事件日期集合
(buildEventDaySet),口径完全一致。
颜色:用主题色 brand(选中日换白),**不取日历本的颜色** ——
圆点只表示这天有安排,若取本色会误导成只有那个本有日程。
## 验证
scripts/test-ics-todo-fields.js:19 项全通过
(保留 PRIORITY/CATEGORIES/X-扩展、特殊字符转义、多 VTODO 只改目标、
缺字段补齐位置、结构完整性)。编译 BUILD SUCCESSFUL。
## 未做
子任务(父子层级 / RELATED-TO):需先确认服务器是否支持,另开工单。
|
2026-11-02 15:47:03 +08:00 |
|
laoyang
|
98c4b6a96f
|
feat: 待办可勾选完成 + 月视图事件圆点 #5 #6
== #6 月视图事件标记(每日期最多一个圆点)==
应用市场反馈希望有事件的日期带标记。此前该功能存在但被移除,
原因是**按日历本逐个渲染**:3 个本 3 个点,15 个本满屏都是点。
- MonthCell 只加**一个布尔** hasEvent,不存每本一个的集合
- 用 buildEventDaySet() 一次遍历把有事件的日期收进 Set,
渲染时 O(1) 查(避免 42 格 × N 事件的 O(n²),本机近 3000 条数据会卡)
- 判定口径与 eventsOfDate 一致(区间相交)→ 跨天事件覆盖的每一天都有点
- 待办不计入(无时间点语义,混进来点会失去意义)
- 视觉用主题色 5vp 小点而非纯红:42 格里 30 个红点会吵,
正是用户嫌乱的同类问题;选中日深底下换白色保证对比度
- 无事件时用等高透明占位,避免行高跳动
== #5 待办勾选完成 ==
先回答关键问题:**系统未开放待办 API**。
本机 SDK 检索 @ohos.calendarManager 全文,todo/VTODO/task 零命中,
Calendar/Event 只处理 VEVENT ⇒ 第三方应用无法读写系统「待办」页签。
故只能在本应用内实现,并已在待办页注明不会出现在系统待办中。
现状是**只读**(点击提示请在源端修改),本次补上写回:
- TodoService.setCompleted():GET 原文 → 改状态字段 → PUT 回写
- EventDb: queryById / setTodoCompleted
- DavClient.getRawStrict():失败**抛错**(原 getRaw 失败返回 HTTP 4xx
字符串,若当 ICS 内容 PUT 回去会把待办覆盖成一句错误信息)
- IcsUtil.rewriteTodoCompletion()
⚠️ 两个关键设计:
1. **不重建 VTODO,只在原文上改字段**
VTODO 有 SUMMARY/DESCRIPTION/DUE/PRIORITY/CATEGORIES/X-* 等字段,
本地库只存了少数几个。重建后 PUT 会把没存的字段全部抹掉(丢数据)。
2. **两遍处理,与字段顺序无关**
RFC 5545 不规定字段顺序。单遍实现若 STATUS 出现在 UID 之前,
matched 仍为 false → 状态改不到 → 用户点完成没反应。
改为第 1 遍定位目标 VTODO 块、第 2 遍在块内改写。
插入补字段时按**块序号**定位而非行号(改动会删掉旧 COMPLETED 行,
行号不再对齐,会让字段落到 END:VCALENDAR 之后,部分服务端直接 400)。
同步维护三个字段(按 RFC 5545,缺一个各客户端显示就不一致):
STATUS / COMPLETED / PERCENT-COMPLETE。
UI:顶部新增「待办」标签(月/周/列表/待办),未完成在前、已完成在后,
点击勾选即写回;写回失败本地状态不变(避免界面与服务器不一致)。
验证:scripts/test-ics-todo.js 覆盖 26 项(状态在 UID 前/后、取消完成、
多 VTODO 只改目标、缺 STATUS 补字段、折行、结构完整性),全部通过。
编译 BUILD SUCCESSFUL。
|
2026-11-02 14:48:43 +08:00 |
|