补齐待办模块最后两项协议能力。 ## #43 子任务(父子结构) ### 协议 `RELATED-TO;RELTYPE=PARENT:<父uid>`,值用**父任务 UID**(不是本地 id—— 父子关系是服务器资源属性,跨设备同步时 UID 才稳定)。 ### 数据层 - `LocalEvent` / `RemoteEvent` / `DisplayEvent` 加 `parentUid` - 表加 `parent_uid` 列,`toBucket`/`fromRow`/`applyRemote` 双向映射 ### UI - 列表:子任务缩进 34vp + 标题前「∟」连线符 - 父任务副行追加子任务进度「N/M」 - 编辑弹层加「父任务」行 → 覆盖层选择(候选 = 未完成顶层任务, 排除自己及后代,防成环) - **父任务勾选完成 → 级联完成所有未完成子任务**(用户选定的语义) ## #44 附件(内联 base64) ### 查证 + 实测(已更新 #44 工单) - iCalendar RFC 5545 原生支持 ATTACH,两种形式:URI / **内联 base64** - RFC 8607 托管附件需服务器特殊支持(群晖没有) - **实测群晖**:PUT 带 `ATTACH;...;ENCODING=BASE64;VALUE=BINARY:<b64>` → 201, GET 回原文原样保留(4558 字符整行、含中文文件名「报告.pdf」都不丢) ### 实现(按标准协议,直接上传同步) - 附件 = VTODO 的 ATTACH 行(内联 base64),随 .ics 一起 PUT 同步 - 不需要自己传文件贴链接 - `buildTodo` / `rewriteTodoFields` 读写 ATTACH;`parseTodos` 解析回填 - 数据层 `attachments` 存 JSON([{name,mime,base64}]),base64 直接存库零转换 - UI:弹层加「附件」区,文件选择器选文件 → 读二进制 → base64 编码 → 随待办保存 ### 限制 最多 3 个附件、单文件 ≤5MB(内联 base64 会让 .ics 膨胀,限制防爆)。 ### 折行决策 **不折行**。原因:① 工程现有 SUMMARY/DESCRIPTION/LOCATION 一贯整行不折; ② 群晖实测 4558 字符整行也能存;③ RFC 折行是 SHOULD 非 MUST,一致性优先; ④ 折行若按 75 octets 硬切会把 UTF-8 中文名(「报告.pdf」)拦腰切断成乱码。 ## 兼容性 `rewriteTodoFields` 新增 `touchParent` / `touchAttach` 哨兵: 编辑只改标题时传 false,服务器上**其他客户端写的 RELATED-TO / ATTACH 原样保留**; 只有用户实际编辑了父任务/附件才 touch=true 重写。 ## 验证 - 编译 `BUILD SUCCESSFUL` - 协议往返(Python 等价复刻):生成→解析 无损,附件 base64 还原正确 - 服务器端到端:PUT(201) + GET 原样返回 RELATED-TO + 中文文件名 ATTACH ## 未验证 真机 UI(设备离线)。需人工验:子任务缩进、级联完成、文件选择器上传、 附件随待办同步到另一客户端。
This commit is contained in:
@@ -13,6 +13,7 @@ import { IcsUtil } from './IcsUtil';
|
||||
/** 界面展示用事件 */
|
||||
export class DisplayEvent {
|
||||
id: number = 0; // 本地库 id 或系统日历事件 id
|
||||
uid: string = ''; // 服务器 UID(待办父子关系用它匹配 parentUid)
|
||||
isSystem: boolean = false;
|
||||
title: string = '';
|
||||
description: string = '';
|
||||
@@ -36,6 +37,10 @@ export class DisplayEvent {
|
||||
categories: string = '';
|
||||
/** 提醒提前分钟数(多选),空 = 不提醒 */
|
||||
reminders: number[] = [];
|
||||
/** 父任务 UID(空 = 顶层任务),对应 RELATED-TO */
|
||||
parentUid: string = '';
|
||||
/** 附件 JSON 数组字符串(含 base64),空 = 无附件 */
|
||||
attachments: string = '';
|
||||
writable: boolean = true; // 所属日历本是否可写(只读时点击显示详情而非编辑)
|
||||
}
|
||||
|
||||
@@ -368,6 +373,7 @@ export class CalendarDataService {
|
||||
}
|
||||
const d = new DisplayEvent();
|
||||
d.id = e.id;
|
||||
d.uid = e.uid;
|
||||
d.isSystem = false;
|
||||
d.title = e.title;
|
||||
d.description = e.description;
|
||||
@@ -382,6 +388,8 @@ export class CalendarDataService {
|
||||
d.priority = e.priority;
|
||||
d.categories = e.categories;
|
||||
d.reminders = e.reminders;
|
||||
d.parentUid = e.parentUid;
|
||||
d.attachments = e.attachments;
|
||||
d.recurRule = e.rrule;
|
||||
d.dtstart = e.dtstart;
|
||||
d.recurring = e.rrule !== '';
|
||||
|
||||
Reference in New Issue
Block a user