diag(同步): 抽出 reportRaw 通用执行器,排查 Inbox 待办拉不到 (#53)

## 排查过程与结论

用户反馈:在 Inbox 新建待办后,列表里看不到。

### 诊断手段
把 `reportComponents` 的 HTTP 执行部分抽成 `reportRaw`,
新增 `reportAll`(不带 comp-filter 的全量 calendar-query)作为对照。

### 关键数据
| 查询 | 结果 |
|---|---|
| Inbox 的 VTODO REPORT | 响应 68 字符,含VTODO=false,响应数=0 |
| Inbox 的全量 REPORT | **722 个资源,全部 VEVENT=true** |
| 娱乐(home) 的 REPORT | **722 个资源** ← 与上面数字完全相同 |
| 待办创建 PUT | `home_todo/todo-1793849023185-qx4b36.ics` → **201 成功** |

### 结论
**群晖把 `home_todo` 解析成了 `home` 的别名**,两个 URL 返回同一份 722 条日程数据。
所以:
1. 待办 PUT 到 `home_todo/todo-xxx.ics`,实际写进了 home 本
2. 按 VTODO 过滤查 `home_todo` → 服务器在这个"别名本"里找不到 VTODO → 返回空
3. 待办永远同步不下来

这不是 App 的 bug,是**服务器端日历本配置问题**(Inbox 指向了错误的存储)。

## 本次改动
- `reportComponents` 拆出 `reportRaw(href, auth, body, compName)`
- 新增 `reportAll(href, auth)`:全量 calendar-query
- 移除临时诊断日志

## 待用户处理
需要在群晖 Calendar Server 后台检查 `home_todo` 这个日历本的真实路径,
或让用户改用其他待办本(如「个人成长」已验证可正常工作)。

## 编译
BUILD SUCCESSFUL
This commit is contained in:
2026-11-05 11:26:37 +08:00
parent 051257e3be
commit 8126c058fa
+16
View File
@@ -465,6 +465,16 @@ export class DavClient {
return DavClient.reportComponents(href, auth, 'VTODO', '');
}
/** 不带 comp-filter 的全量 calendar-query(诊断用) */
static async reportAll(href: string, auth: string): Promise<RemoteItem[]> {
const body: string = '<?xml version="1.0" encoding="utf-8"?>' +
'<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">' +
'<d:prop><d:getetag/><c:calendar-data/></d:prop>' +
'<c:filter><c:comp-filter name="VCALENDAR"/></c:filter>' +
'</c:calendar-query>';
return DavClient.reportRaw(href, auth, body, 'ALL');
}
/** 通用 REPORT:按组件类型过滤拉取 calendar-data + getetag */
private static async reportComponents(href: string, auth: string,
compName: string, timeRange: string): Promise<RemoteItem[]> {
@@ -475,6 +485,12 @@ export class DavClient {
`<c:comp-filter name="${compName}">` +
timeRange +
'</c:comp-filter></c:comp-filter></c:filter></c:calendar-query>';
return DavClient.reportRaw(href, auth, body, compName);
}
/** 通用 REPORT 执行器:传完整 body,返回解析后的资源列表 */
static async reportRaw(href: string, auth: string, body: string,
compName: string): Promise<RemoteItem[]> {
const httpRequest = http.createHttp();
try {
const resp: http.HttpResponse = await httpRequest.request(href, {