待办(VTODO):系统未开放待办 API,需在本应用内实现可读写(现为只读) #5

Closed
opened 2026-11-02 06:36:55 +00:00 by laoyang · 1 comment
Owner

用户反馈(应用市场评价)

CardDav 当中其实还有一个待办。咱们的手机不知道能不能同步到咱们的应用,
也不知道能不能把它同步到手机上。
华为手机有待办功能吗?还是说这样的话,我们需要在咱们的应用当中也增加一个同步待办的功能?

先回答两个问题

① 华为手机有待办功能吗?—— 有

系统日历 App 底部有「待办」页签,可新建待办、勾选完成、设每日重复,
并与「备忘录」打通(带时间的备忘录可同步进日历)。
(依据:华为消费者官网支持文档 + 系统日历实测路径;具体入口随系统版本略有差异。)

② 能不能同步到手机系统待办?—— 不能

系统没有对外开放待办 API。 本机 SDK(command-line-tools 26.0.0.851 / API 26)检索:

$ ls $API | grep -i calendar
@ohos.calendarManager.d.ts          ← 只有这一个

$ grep -rniE 'todo|VTODO|task' $API/@ohos.calendarManager.d.ts
(无命中)

$ grep -rliE 'calendartodo|todoManager|@ohos.*todo' $API
(无命中)

CalendarManager / Calendar / Event 这一整套只处理日程(VEVENT),
没有 Todo 对象、没有 TodoType、没有待办相关接口。
⇒ 第三方应用无法读写系统待办,这条路走不通。

(顺带说明:Event 里也没有 TODO 这种 type。所以"把待办塞进系统日历伪装成日程"
虽然技术上能写进去,但会在系统日历里变成一个普通日程,语义不对,不建议。

现状:应用内已经在同步待办了,但是只读

已有能力(不是从零做):

环节 实现位置 状态
拉取 VTODO DavClient.reportTodos() → reportComponents(href, auth, 'VTODO', '') ✅ 有
解析 VTODO IcsUtil(BEGIN:VTODO / END:VTODO) ✅ 有
落库 EventDb:kind='todo'、isTodo、completed(STATUS:COMPLETED) ✅ 有
查询 EventDb.todos()、CalendarDataService ✅ 有
展示 Index.todoBody():未完成 / 已完成分组,按截止时间升序 ✅ 有
交互 点击弹提示「待办来自服务器,请在群晖日历等源端修改」 ⚠️ 只读
新建 / 编辑 / 完成 — ❌ 完全没有

EventEditPage.ets 里 grep todo 零命中,DavClient 也没有 PUT VTODO 的写入路径。

所以本条真正的缺口

不是"要不要加待办",而是把只读待办升级为可读写:

  1. 新建待办:标题、截止时间、优先级、备注
  2. 编辑待办:同上
  3. 勾选完成 / 取消完成:写回 STATUS:COMPLETED / STATUS:NEEDS-ACTION,
    以及 COMPLETED: 时间戳、PERCENT-COMPLETE
  4. 删除待办
  5. 写回走 PUT(新建用 PUT + 随机 uuid 文件名;更新沿用 ETag 防冲突),
    与现有日程推送同一套逻辑

⚠️ 需要用户决策的点

这条的工作量远大于另外两条:现有日程的写入链路(ETag、冲突处理、离线队列、
重复规则、镜像快照)是长期打磨出来的,待办要做成同等质量需要不少功夫。

建议拆成两期,先确认用户要哪个:

方案 内容 价值
A. 先做"勾选完成" 只加"点圆圈 → 写回 STATUS:COMPLETED" 投入小,覆盖最高频操作(待办的核心就是"划掉")
B. 完整读写 新建 / 编辑 / 完成 / 删除 全套 完整,但工作量大
C. 只读维持现状 只改善提示语,说明为什么不能同步到系统待办 零成本,但没解决用户诉求

推荐 A 先行,验证写入链路稳定后再补 B。

另一件事:需要在应用内说明"为什么系统待办里没有"

用户很容易以为"同步了就该在系统待办里看到"。建议在待办页加一行说明:
「系统未开放待办接口,本应用内的待办不会出现在系统日历的待办页签中」。
这能减少误报和差评。

验收标准(按选定方案)

  • A:点击未完成待办的圆圈 → 变勾选态 → 服务器上 STATUS 变 COMPLETED →
    下拉刷新后仍是已完成;点击已完成 → 可取消回未完成。
  • B:A 的全部 + 能新建/编辑/删除待办并正确回写服务器。
  • 待办页有明确说明"不会进入系统待办"。
  • 不影响现有日程同步(回归:日程增删改仍正常)。
  • 编译通过 + 真机验证。

为什么单独建单

应用市场用户反馈的第2条;虽然与 #3 都涉及系统日历,但 #3 是清镜像残留,本条是 VTODO 待办读写与系统待办不可同步的说明

## 用户反馈(应用市场评价) > CardDav 当中其实还有一个待办。咱们的手机不知道能不能同步到咱们的应用, > 也不知道能不能把它同步到手机上。 > 华为手机有待办功能吗?还是说这样的话,我们需要在咱们的应用当中也增加一个同步待办的功能? ## 先回答两个问题 ### ① 华为手机有待办功能吗?—— **有** 系统日历 App 底部有「待办」页签,可新建待办、勾选完成、设每日重复, 并与「备忘录」打通(带时间的备忘录可同步进日历)。 (依据:华为消费者官网支持文档 + 系统日历实测路径;具体入口随系统版本略有差异。) ### ② 能不能同步到手机系统待办?—— **不能** **系统没有对外开放待办 API。** 本机 SDK(command-line-tools 26.0.0.851 / API 26)检索: ``` $ ls $API | grep -i calendar @ohos.calendarManager.d.ts ← 只有这一个 $ grep -rniE 'todo|VTODO|task' $API/@ohos.calendarManager.d.ts (无命中) $ grep -rliE 'calendartodo|todoManager|@ohos.*todo' $API (无命中) ``` `CalendarManager` / `Calendar` / `Event` 这一整套只处理**日程(VEVENT)**, 没有 Todo 对象、没有 TodoType、没有待办相关接口。 ⇒ **第三方应用无法读写系统待办**,这条路走不通。 (顺带说明:`Event` 里也**没有** TODO 这种 `type`。所以"把待办塞进系统日历伪装成日程" 虽然技术上能写进去,但会在系统日历里变成一个普通日程,语义不对,不建议。 ## 现状:应用内**已经**在同步待办了,但是只读 已有能力(不是从零做): | 环节 | 实现位置 | 状态 | |---|---|---| | 拉取 VTODO | `DavClient.reportTodos()` → `reportComponents(href, auth, 'VTODO', '')` | ✅ 有 | | 解析 VTODO | `IcsUtil`(`BEGIN:VTODO` / `END:VTODO`) | ✅ 有 | | 落库 | `EventDb`:`kind='todo'`、`isTodo`、`completed`(`STATUS:COMPLETED`) | ✅ 有 | | 查询 | `EventDb.todos()`、`CalendarDataService` | ✅ 有 | | 展示 | `Index.todoBody()`:未完成 / 已完成分组,按截止时间升序 | ✅ 有 | | 交互 | 点击弹提示「待办来自服务器,请在群晖日历等源端修改」 | ⚠️ **只读** | | 新建 / 编辑 / 完成 | — | ❌ **完全没有** | `EventEditPage.ets` 里 `grep todo` **零命中**,`DavClient` 也**没有** PUT VTODO 的写入路径。 ## 所以本条真正的缺口 不是"要不要加待办",而是**把只读待办升级为可读写**: 1. **新建待办**:标题、截止时间、优先级、备注 2. **编辑待办**:同上 3. **勾选完成 / 取消完成**:写回 `STATUS:COMPLETED` / `STATUS:NEEDS-ACTION`, 以及 `COMPLETED:` 时间戳、`PERCENT-COMPLETE` 4. **删除待办** 5. 写回走 `PUT`(新建用 `PUT` + 随机 uuid 文件名;更新沿用 ETag 防冲突), 与现有日程推送同一套逻辑 ## ⚠️ 需要用户决策的点 **这条的工作量远大于另外两条**:现有日程的写入链路(ETag、冲突处理、离线队列、 重复规则、镜像快照)是长期打磨出来的,待办要做成同等质量需要不少功夫。 建议拆成两期,先确认用户要哪个: | 方案 | 内容 | 价值 | |---|---|---| | **A. 先做"勾选完成"** | 只加"点圆圈 → 写回 STATUS:COMPLETED" | 投入小,覆盖最高频操作(待办的核心就是"划掉") | | **B. 完整读写** | 新建 / 编辑 / 完成 / 删除 全套 | 完整,但工作量大 | | **C. 只读维持现状** | 只改善提示语,说明为什么不能同步到系统待办 | 零成本,但没解决用户诉求 | **推荐 A 先行**,验证写入链路稳定后再补 B。 ## 另一件事:需要在应用内说明"为什么系统待办里没有" 用户很容易以为"同步了就该在系统待办里看到"。建议在待办页加一行说明: 「系统未开放待办接口,本应用内的待办不会出现在系统日历的待办页签中」。 这能减少误报和差评。 ## 验收标准(按选定方案) - **A**:点击未完成待办的圆圈 → 变勾选态 → 服务器上 `STATUS` 变 `COMPLETED` → 下拉刷新后仍是已完成;点击已完成 → 可取消回未完成。 - **B**:A 的全部 + 能新建/编辑/删除待办并正确回写服务器。 - 待办页有明确说明"不会进入系统待办"。 - 不影响现有日程同步(回归:日程增删改仍正常)。 - 编译通过 + 真机验证。 --- ### 为什么单独建单 应用市场用户反馈的第2条;虽然与 #3 都涉及系统日历,但 #3 是清镜像残留,本条是 VTODO 待办读写与系统待办不可同步的说明
Author
Owner

已随 0.2.0 完成,关闭。

应用内 VTODO 读写已实现

能力 状态
拉取 VTODO(REPORT calendar-query VTODO) ✅
解析 ICS(含 DUE / DTSTART / RRULE / STATUS) ✅
列表展示(按日历本分组、未完成在前) ✅
勾选完成(回写服务器) ✅
编辑标题 / 备注 / 截止时间 ✅
循环待办(完成后跳下一轮) ✅

本单最重要的一处修复

待办数据此前从未被同步过。 同步主循环全程只处理 VEVENT:

  • reportEtags 的 comp-filter 只写 VEVENT
  • queryByCalKey(..., 'event') 只查 kind='event'
  • applyRemote(..., isTodo) 的 isTodo 从未传过 true

而 DavClient.reportTodos() 虽然早就写好,全项目零调用(死代码)。
所以待办只靠历史残留在撑,一旦行被清掉(如取消勾选本触发 pruneStaleHrefs)
就永久消失。

已在 SyncEngine.syncAccountInner 接入 VTODO 同步,并对未知类型本也拉一次
(服务器多半不声明 supported-calendar-component-set,宁可多拉不能漏)。
待办同步整段包在 try/catch 内,单本失败不影响日程同步。

待办标签显示条件

最终实现:todos.length > 0 就显示。

中途曾加过一层「必须勾选了 todo 类型的本」判定,但它依赖
acc.calendarComps(来自服务器的 supported-calendar-component-set)——
本环境拿不到该属性,字段恒空 ⇒ 判定恒 false ⇒ 明明有待办也不显示标签。
该判定已移除。

loadTodos 内部已按 visibleKeys(用户勾选的日历本)过滤,
所以「有待办数据」天然等价于「勾选范围内确实有待办」,
用户一个待办本都没勾时必然是 0 —— 原需求已覆盖。

未完成部分(已拆单)

镜像到系统日历的待办:系统未开放待办 API,技术上不可行。
已拆出 #7 记录查证结论,留档备查。

真机验证

同步日志:

日历本[5]「家庭计划」REPORT 返回 0 个资源 → 待办同步:3 条
日历本[6]「工作任务」REPORT 返回 0 个资源 → 待办同步:2 条
日历本[7]「个人成长」REPORT 返回 0 个资源 → 待办同步:2 条

(这几本 VEVENT 为 0、只有 VTODO,正是纯待办本)

界面 dump:顶部标签 同步日历|今天|月|周|列表|待办|2026年11月,待办标签存在 ✅

已随 0.2.0 完成,关闭。 ## 应用内 VTODO 读写已实现 | 能力 | 状态 | |---|---| | 拉取 VTODO(REPORT calendar-query VTODO) | ✅ | | 解析 ICS(含 DUE / DTSTART / RRULE / STATUS) | ✅ | | 列表展示(按日历本分组、未完成在前) | ✅ | | 勾选完成(回写服务器) | ✅ | | 编辑标题 / 备注 / 截止时间 | ✅ | | 循环待办(完成后跳下一轮) | ✅ | ## 本单最重要的一处修复 **待办数据此前从未被同步过。** 同步主循环全程只处理 VEVENT: - `reportEtags` 的 comp-filter 只写 VEVENT - `queryByCalKey(..., 'event')` 只查 kind='event' - `applyRemote(..., isTodo)` 的 isTodo 从未传过 true 而 `DavClient.reportTodos()` 虽然早就写好,**全项目零调用**(死代码)。 所以待办只靠历史残留在撑,一旦行被清掉(如取消勾选本触发 pruneStaleHrefs) 就永久消失。 已在 `SyncEngine.syncAccountInner` 接入 VTODO 同步,并对未知类型本也拉一次 (服务器多半不声明 supported-calendar-component-set,宁可多拉不能漏)。 待办同步整段包在 try/catch 内,单本失败不影响日程同步。 ## 待办标签显示条件 最终实现:`todos.length > 0 就显示`。 中途曾加过一层「必须勾选了 todo 类型的本」判定,但它依赖 `acc.calendarComps`(来自服务器的 supported-calendar-component-set)—— **本环境拿不到该属性**,字段恒空 ⇒ 判定恒 false ⇒ 明明有待办也不显示标签。 该判定已移除。 `loadTodos` 内部已按 visibleKeys(用户勾选的日历本)过滤, 所以「有待办数据」天然等价于「勾选范围内确实有待办」, 用户一个待办本都没勾时必然是 0 —— 原需求已覆盖。 ## 未完成部分(已拆单) **镜像到系统日历的待办**:系统未开放待办 API,技术上不可行。 已拆出 #7 记录查证结论,留档备查。 ## 真机验证 同步日志: ``` 日历本[5]「家庭计划」REPORT 返回 0 个资源 → 待办同步:3 条 日历本[6]「工作任务」REPORT 返回 0 个资源 → 待办同步:2 条 日历本[7]「个人成长」REPORT 返回 0 个资源 → 待办同步:2 条 ``` (这几本 VEVENT 为 0、只有 VTODO,正是纯待办本) 界面 dump:顶部标签 `同步日历|今天|月|周|列表|待办|2026年11月`,待办标签存在 ✅
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/SyncCalendar#5