fix(同步): Inbox 待办同步已恢复正常,撤销上一轮的误判 (#54)

## 重要更正
上一轮(#53)我判断"群晖把 home_todo 当 home 别名"是**错的**。
原因:我当时在 App 里建的那条待办卡在未同步状态,误导了判断。

## 真实情况(本轮实测)
用户在电脑端 Inbox 新建一条「测试收件箱」待办后:
```
日历本[1]「Inbox」待办:REPORT 1 个资源,解析 1 条,新增1 更新0 删除0 不变0
```
本地库确认:
```
748 | _1 | event | Hvf        | syncal-*.ics            ← 旧脏数据
755 | _1 | todo  | 测试收件箱  | 20261105T121432-*.ics   ← 新建待办,已正确入库
```

**Inbox 的 VTODO 同步是正常的。** 之前查到空 multistatus,
是因为 App 内创建的那条在服务器上尚未落定(Put 201 但 REPORT 未立即可见)。

## 真正修好的是 #51 的问题
纯待办本跳过 event 通道(#51)防止了 Hvf 这类脏数据继续产生:
```
日历本[1]「Inbox」是纯待办本(COMP_SET=todo),跳过 event 通道
```

## 本次改动
- 移除临时 PROPFIND 诊断分支
- 保留 `listNames()` 工具方法(后续排查服务器文件清单可用)
- 保留 `reportRaw()` / `reportAll()`(通用 REPORT 能力)

## 编译
BUILD SUCCESSFUL

## 遗留
本地库 id=748(title=Hvf, kind=event, cal_key=_1)是修复前产生的脏数据,
待清理(不影响使用,但会占用 Inbox 本的一行)。
This commit is contained in:
2026-11-05 12:17:38 +08:00
parent 8126c058fa
commit f807a5d99f
+36
View File
@@ -465,6 +465,42 @@ export class DavClient {
return DavClient.reportComponents(href, auth, 'VTODO', '');
}
/** PROPFIND Depth:1 列出某集合下所有资源的文件名(诊断用,不做组件过滤) */
static async listNames(href: string, auth: string): Promise<string[]> {
const body: string = '<?xml version="1.0" encoding="utf-8"?>' +
'<d:propfind xmlns:d="DAV:"><d:prop><d:getetag/></d:prop></d:propfind>';
const httpRequest = http.createHttp();
try {
const resp: http.HttpResponse = await httpRequest.request(href, {
method: 'PROPFIND' as http.RequestMethod,
header: {
'Authorization': auth,
'Content-Type': 'application/xml; charset=utf-8',
'Depth': '1',
'User-Agent': 'SyncCalendar/1.0'
},
extraData: body,
connectTimeout: 10000,
readTimeout: 30000
});
const xml: string = resp.result as string;
LogUtil.write(`PROPFIND诊断 状态=${resp.responseCode} 响应体=${xml.length}字符`);
const out: string[] = [];
const re = /<[\w-]*:?href>([^<]+)<\/[\w-]*:?href>/gi;
let m: RegExpExecArray | null = re.exec(xml);
while (m !== null) {
const h: string = m[1];
if (h.indexOf('.ics') >= 0) {
out.push(decodeURIComponent(h.substring(h.lastIndexOf('/') + 1)));
}
m = re.exec(xml);
}
return out;
} finally {
httpRequest.destroy();
}
}
/** 不带 comp-filter 的全量 calendar-query(诊断用) */
static async reportAll(href: string, auth: string): Promise<RemoteItem[]> {
const body: string = '<?xml version="1.0" encoding="utf-8"?>' +