待办事务tasks

一、起点归纳:我现在的实际状况

  • 桌面:NixOS + Plasma 6.6.6。Ctrl+Alt+Shift+Q(我口头说的 Ctrl+Shift+Alt+Q)绑的是 KDE 便签 plasmoid(kglobalshortcutsrc 里 activate widget 231 / 716),便签正文存 ~/.local/share/plasma_notes/,是自由文本 HTML。
  • 便签的问题:没有完成态、没有截止时间、没有分组、不能跨端、不能定时提醒 → 记完就烂在文本里,只能"翻旧账"。
  • 已有 Google Tasks 数据:账号已 OAuth 授权(token 在 ~/.hermes/google_token.json),8 个清单:AI电脑手机 / 跬步 / 启城 / 雅阁 / 钱库 / 同学 / 同道 / 飞度。
  • Google Tasks 的问题(本机实测):经代理单次 API 3–6 s、discovery 文档 11.6 s;官方无 Linux 客户端;视图只有列表;重复任务没有工作日/农历规则;提醒能力弱。
  • 手机:Android,需要在桌面放小部件随时看待办。
  • 服务器:自有云服务器,可跑 docker-compose;只接受 docker-compose.yml 这一种私有化方式。
  • 取舍:可以接受私有化运维,但不能为它付太多;最高频的动作必须 0 摩擦(一次按键 → 弹窗 → 回车)。

二、目标与需求清单(R01–R17,逐条验收)

编号需求硬/软判据(怎么算满足)
R01NixOS 桌面全局快捷键 Ctrl+Shift+Alt+Q 一键唤醒弹窗硬按键到输入框可打字 < 200 ms,不打开浏览器
R02弹窗内可"快速操作":记一条 / 勾完成 / 改期硬三个动作都不需要切窗口、不需要登录
R03桌面视图强大:日 / 周 / 月 / 年硬四种时间尺度都能一眼看完负载
R04数据管理强大:分组 / 项目 / 标签 / 子任务 / 搜索硬能把 8 个清单的结构无损迁过去并继续用
R05组件调用轻便灵活(可被脚本/CLI/API 直接调用)硬有稳定 HTTP API 或 CLI,我能写一行脚本就落库
R06Android 桌面小部件快速查看待办硬桌面直接看到未完成清单,不用点开 App
R07Android 端可完整操作(增删改 / 完成 / 看大描述)硬手机上能处理,不用回桌面
R08农历(农历日期 / 农历重复,如生日、祭日)硬(当前无解)能按农历每月/每年重复,且能看农历日期
R09工作日规则(工作日重复、含调休认知)硬能设"每周一~周五",调休需能手工覆盖
R10周期性任务(天 / 周 / 月 / 自定义间隔)硬RRULE 级别或等价的自然语言重复
R11一次性定时提醒(指定日期时刻通知)硬到点有通知(手机或桌面),不依赖我盯着
R12标题 + 大篇幅描述硬描述能写几百字,支持换行/简单排版
R13分组(清单 / 项目 / 子任务层级)硬至少两级结构 + 标签或筛选
R14多端同步(NixOS ↔ Android)硬任一端改动,另一端口径一致,延迟可接受
R15已有 Google Tasks 数据可迁移或共存硬8 个清单的标题/描述/完成态都能过去
R16私有化只接受 docker-compose.yml硬一条 docker compose up -d 能起全栈
R17运维成本可控(备份 / 升级 / 证书)软不引入多个常驻组件,升级不破数据

符号约定:✅ 已核实满足;⚠️ 部分满足 / 需自建桥接 / 未复核;❌ 不满足;— 不适用。

三、方案总表(一行一个方案)

方案许可 / 托管服务端 composeNixOS 桌面形态桌面热键弹窗Android 小组件视图(日周月年)农历工作日 / 周期重复定时提醒标题 + 大描述分组多端同步Google Tasks 迁移结论
Google Tasks(现状基线)商业云❌ 不可自建Chrome 应用窗口 + 我的 todo 脚本✅ 已实测 32 ms 落盘(本地 outbox)✅ 官方 App 有小部件❌ 只有列表❌⚠️ 只有简单重复,工作日要手选⚠️ 弱(到期日 + 基础提醒)✅⚠️ 清单 + 子任务,无标签✅—(数据就在这)留作基线:采集已解决,视图/农历是硬缺口
VikunjaAGPL / 自托管✅ 官方 docker 镜像Web / PWA(无官方 Linux 原生客户端:go-vikunja/desktop 已 archived)✅ 走 REST API,采集逻辑与现脚本一致✅ 代码证据:android/.../widget/AppWidget.kt + res/xml/widget.xml⚠️ 列表 / 看板 / 甘特(表格、日历视图未复核)❌✅ 周期(RepeatAfter + quickAddMagic 自然语言);⚠️ 工作日靠"每周 + 选星期"✅ 有提醒(ReminderDetail,邮件/桌面通知)✅ Markdown✅ 项目 / 标签 / 子任务✅⚠️ 有 CSV 导入,Google Tasks 需我写脚本走 API综合最匹配(自托管 + 双端 + 提醒 + 小部件)
Tasks.org + Radicale(CalDAV)GPL / 自托管✅ Radicale 极简 compose无官方 Linux 客户端;靠 KOrganizer / Evolution(Akonadi 原生)⚠️ 需自建 CalDAV PUT 脚本(可写)✅✅ 最成熟:仓库 33 个 widget 相关文件(org/tasks/widget/AppWidgetManager.kt)⚠️ 列表 + 日历视图(年视图未复核)❌✅ RRULE 完整(含 BYDAY 工作日)✅ VALARM 本地闹钟✅✅ 列表 / 子任务 / 标签✅✅✅ 最干净:Google Tasks → ICS VTODO → 直接 PUT 进 Radicale安卓体验最强 + 迁移最省力;桌面原生度依赖 PIM 栈
Nextcloud TasksAGPL / 自托管✅(整套 Nextcloud 较重)Web⚠️ 需自建 CalDAV 脚本— 无官方 App,靠 DAVx5 + Tasks.org❌ 列表 / 智能集合❌✅ CalDAV RRULE✅ VALARM✅✅✅✅ ICS只有已在用 Nextcloud 才值得,否则 Radicale 更轻
Tududi开源 / 自托管✅Web / PWA⚠️ 需走其 API— 无自有 App,靠 CalDAV + Tasks.org⚠️ 项目 / 列表视图❌✅ 强(日/周/月/每月某星期/月末/按完成日重复)⚠️ 有通知(remind 相关,细节未复核)✅✅ 项目 / 任务 / 笔记⚠️ CalDAV 双向⚠️轻量备选;手机能力外包给 Tasks.org
Donetick开源 / 自托管✅Web / PWA⚠️ 需走其 API❌ 仓库 296 个文件里 widget 相关 0 个❌❌✅ 按到期日/完成日重复✅ 多平台通知(含 Android APK)✅⚠️ 家务协同模型(家庭/成员)✅❌场景不匹配(家务/积分/打卡)
Super ProductivityMIT / 客户端 + 自建同步⚠️ 仓库有 packages/super-sync-server,但它是"同步服务"不是"任务服务端"Electron 原生客户端(Linux 有包)⚠️ 客户端内快捷键(全局弹窗未复核)⚠️ 未复核⚠️ 今日 / 看板 / 时间盒(无月/年视图)❌✅ 有重复⚠️✅✅✅❌唯一真差异 = 时间追踪/番茄钟;不是"服务端 + 多端"模型
FocalboardMIT·社区维护✅Web + 桌面端⚠️⚠️ 未复核❌ 看板模型❌❌ 无重复❌ 无提醒✅✅ 看板/卡片⚠️❌不选:看板思维 + 已移交 community / Mattermost 不再主推
TickTick 滴答清单(商业对照)商业云(非自托管)❌Web / 第三方客户端(无官方 Linux 客户端)⚠️ 需自建 PWA 壳✅ 成熟小部件✅ 日 / 周 / 月 / 日历 / 清单⚠️ 官方宣称支持农历重复,本次未取到页面证据(未复核)✅ 工作日重复✅ 定时提醒✅✅✅⚠️ 有导入,细节未复核功能最贴需求,但数据在商业云 → 与自托管目标冲突,只作对照
Mindwtr开源 / 自托管✅(另有第三方 nix flake)有桌面端⚠️⚠️ 未复核⚠️ GTD 流程视图❌✅ 有重复⚠️✅✅ GTD 语境/项目✅ 自建云同步❌GTD 专精,2294★;不如 Vikunja 通用
Pomodoist开源 / 自托管✅Web / PWA⚠️⚠️ 未复核❌❌⚠️⚠️✅⚠️⚠️❌番茄专精(542★),无采集/小部件增量
nia-todo开源 / 自托管✅Web / PWA⚠️❌❌❌⚠️❌✅⚠️⚠️❌仅 9★(2026-10 新建),太早期,不作候选
HamsterBase开源 / 自托管✅Web——————————淘汰:官方定位是 "self-hosted, local-first web archive",不是任务应用

四、需求 × 方案覆盖矩阵(R01–R17)

只列四个真正可当选的方案 + 商业对照。每一行独立核对,不合并。

需求Google TasksVikunjaTasks.org + RadicaleTududiTickTick(对照)
R01 桌面热键弹窗✅ 现有脚本 32 ms✅ 换 endpoint 即可⚠️ 需写 CalDAV 脚本⚠️ 需走 API⚠️ 只能 PWA 壳
R02 弹窗内快速操作✅ 记/勾完成已实现,改期待补✅ 走 API 全支持✅ PUT/PROPPATCH✅⚠️ 无公开 API 承诺
R03 日/周/月/年视图❌⚠️ 有甘特/看板,日历视图未复核⚠️ 有日历视图,年视图未复核⚠️ 列表为主✅
R04 数据管理(分组/标签/子任务)⚠️ 清单+子任务,无标签✅ 项目/标签/子任务/筛选✅ 列表/子任务/标签✅ 项目/任务/笔记✅
R05 组件可调用(API/CLI)✅(本机已接)✅ REST API 完整✅ CalDAV 标准协议✅ API❌ 无公开 API
R06 Android 小部件✅✅ 代码证据 AppWidget.kt✅✅ 最成熟❌(靠 Tasks.org)✅
R07 Android 完整操作✅✅ 官方 App(613★)✅⚠️ 靠 Tasks.org✅
R08 农历❌❌❌❌⚠️ 未复核
R09 工作日规则⚠️ 手选周一~周五⚠️ 每周+选星期✅ RRULE BYDAY✅ 可设每月某星期✅
R10 周期任务⚠️ 简单重复✅ 含自然语言✅ RRULE✅ 含按完成日重复✅
R11 一次性定时提醒⚠️ 弱✅ 提醒组件✅ VALARM 本地闹钟⚠️ 细节未复核✅
R12 标题 + 大描述✅✅ Markdown✅✅✅
R13 分组⚠️✅✅✅✅
R14 多端同步✅✅✅ CalDAV⚠️ CalDAV 双向✅
R15 Google Tasks 迁移—⚠️ 需脚本/CSV✅✅ ICS VTODO 直灌⚠️⚠️ 未复核
R16 只接受 compose❌ 不可自建✅✅✅❌
R17 运维可控✅ 零运维⚠️ 1 容器 + 备份⚠️ 1 容器 + 可选 PIM 栈⚠️ 1 容器✅ 零运维

五、一阶实施:tasks 窗口

  • 方案:用 Google 官方网页,Chrome 应用窗口打开;Ctrl+Alt+Shift+Q 一个键进,进去就是谷歌原生全功能界面(清单 / 子任务 / 描述 / 日期 / 完成 / 删除)
  • 持久化:

5.1 定稿形态

项内容
快捷键只占 Ctrl+Alt+Shift+Q → Chrome 应用窗口打开 https://tasks.google.com/(--app= 模式,无地址栏/标签栏)
系统载体/etc/nixos/modules/desktop/office/chrome_ui_tasks.nix(office 域扩展)+ 桌面条目 hermes-todo-open.desktop(NoDisplay)
命令行(无快捷键)todo ls / add / refresh / sync / done / undo / due / list / web;todo web 等同按 Q
数据仍是自己的 Google 账号与 8 个清单,不迁移、不复制

5.2 全局快捷键能生效的两个必需条件(踩过两次)

  • 桌面条目必须带 X-KDE-GlobalAccel-CommandShortcut=true:KDE 靠它识别"这条 .desktop 可当全局快捷键"。缺了 → 快捷键设置里看得见组件,但按键永不触发。
  • kglobalshortcutsrc 的 _launch 必须写单值(如 _launch=Ctrl+Alt+Shift+Q):写成 KConfig 三段式(值,默认,友好名)会被 kglobalaccel 静默丢弃,配置里看得见、按键没反应。
  • 验收判据(不用手按):qdbus --literal org.kde.kglobalaccel /kglobalaccel org.kde.KGlobalAccel.getGlobalShortcutsByKey 234881105,应返回 _launch / 待办:Google Tasks / hermes-todo-open.desktop。键值编码 = (修饰键<<24)|Qt::Key,Ctrl+Alt+Shift = 0x0E,Q = 0x51。

5.3 单例:试过两版,已全部撤销

版本做法结果
v1xdotool search --onlyvisible 找窗口 → 有则激活❌ --onlyvisible 只返回当前桌面视口内的窗口,窗口在别的桌面/还没映射就找不到 ⇒ 照样叠窗
v2记窗口 XID 到状态文件,先验活再激活;失效则按标题认领;确实没有才启动并轮询抓 XID❌ 实测"按几次还是几个实例"
现状全部删除:todo-open 脚本、xdotool 依赖、状态文件、识别逻辑按一次开一个,不再做任何窗口识别(接受这个行为)

5.4 窗口大小:为什么每次都是半屏(已修)

  • 现象:每次打开都是"半屏 + 高度锁死改不动",不认上次关闭的大小/位置。
  • 取证:xprop _NET_WM_STATE 显示 MAXIMIZED_VERT(垂直最大化 ⇒ 高度锁死);Chrome Preferences 里 browser.app_window_placement.tasks.google.com_/ 存的是老的半屏矩形;主 profile 加 --window-size/--window-position 被忽略;换成全新 --user-data-dir 启动则完全正常(900×700 生效)⇒ 不是 KWin,也不是参数问题;主进程还会用内存里的旧值把磁盘上新写的值覆盖回去。
  • 解决:给这个窗口加 KWin 窗口规则「记住上次大小与位置」,声明式写在 /etc/nixos/modules/system/service/kwin-data/kwin-hotkey-router-rules.yml(positionrule=4 / sizerule=4,初始值 2020,1120 / 1400×1000,匹配 wmclass=Google-chrome + wmname=Tasks),rebuild 时合并进 ~/.config/kwinrulesrc 并即时重载 KWin。
  • 实测:关窗重开后回到 1400×1000 @ (2020,1120),且不再带 MAXIMIZED_VERT。以后拖动窗口,KWin 按"记住"策略沿用新位置。

5.5 验收数据(本机实测)

项结果
getGlobalShortcutsByKey 234881105返回 _launch / 待办:Google Tasks / hermes-todo-open.desktop(W 键 234881111 返回空,未被占用)
todo refresh8 个清单、29 项未完成(经代理约 6 s)
todo ls「AI电脑手机」11 项,带截止日;读本地缓存秒回
todo add "xxx @明天"落盘后后台 sync 自动推到 Google(探针任务已清理)

5.6 遗留 / 下一步

  • 把 tasks.google.com 用 Chrome「安装页面为应用」装成真正的 PWA:有独立 app id 与窗口状态,可能同时解决单例与窗口记忆(未实测,值得一试)。
  • R01/R02 的"按键 < 200 ms 就地录一条"目前由命令行 todo add 承担(无快捷键);若要快捷键快记,再单独分配一个键(不占用 W)。
  • R03 视图、R08 农历、R09 调休、R11 定时提醒:Google Tasks 侧无解,留给二阶(自托管 CalDAV / Vikunja)。