把 Windows 任务栏时钟改造成日历 + AI 私人秘书:Tauri 2 + Rust 实现记录

最近把自用的 Windows 桌面日历整理成了可发布的版本,无登录、无账号、无广告、无订阅的单文件绿色版免安装 。这个工具做的事一句话能说清:左键点任务栏时钟,日历就在时钟上方展开;不用它的时候,它安静得像不存在。发到技术社区主要是记录实现过程,跟做 Windows 桌面端的朋友交流踩坑经验。

工具做了什么

  • 任务栏时钟即入口:左键呼出面板,右键是自绘快捷卡片(组件开关 / 鼠标穿透 / 开机启动 / 退出),托盘常驻,支持开机自启。
  • 9 个桌面组件 :今日安排、桌面月历、世界时钟、时间进度、天气、番茄钟、秒表、便笺、倒计时;支持拖动、缩放、透明度、锁定、鼠标穿透,单个可收成 40px 摘要条,Ctrl+Alt+H 一键专注模式。
  • 日历与提醒:农历、节气、节假日调休、黄历宜忌;日程支持自然语言输入、重复规则、多提前提醒点;整点报时 / 久坐提醒 / 日程提醒可换音色与语速。
  • 数据全本地:SQLite,无账号、无广告、不联网(AI 与天气除外);删除的日程 / 待办 / 便签进回收站保留 30 天,可搜索恢复。
  • AI 私人秘书(自备 Key):不是只会聊天,能读写真实日程与待办;

技术栈

  • Tauri 2 + Rust:窗口、任务栏、托盘、全局热键、提醒、SQLite、天气与 AI 请求全在 Rust 侧。
  • React 19 + TypeScript + Vite:面板、设置、组件 UI;antd + dayjs + lunar-typescript。
  • SQLite(rusqlite):本地数据,不依赖服务端。
  • Windows API + UIA:定位任务栏时钟、DPI / 多屏、鼠标穿透、窗口层级。
  • WebView2:运行环境,Win11 与装过 Edge 的系统自带。

几个实现点

1. 找到任务栏时钟的位置

Windows 没有公开的「任务栏时钟坐标」API,用 UI Automation 逐层找:Win11 优先 Time / Date 文本块,Win10 找 ClockButton,再准备 class name 兜底。

rust 复制代码
let time = uia_find_by_id(&automation, root, UIA_ID_TIME);
let date = uia_find_by_id(&automation, root, UIA_ID_DATE);
match (time, date) {
    (Some(t), Some(d)) => return Some(rect_union(t, d)),
    (Some(t), None) => return Some(t),
    (None, Some(d)) => return Some(d),
    (None, None) => {}
}

最麻烦的不是找一次,而是任务栏重启、分辨率变化、多屏切换、DPI 缩放之后要重新算。做法是缓存时钟矩形 + 低频刷新 + 鼠标命中检测兜底。

2. 无边框窗口 + 鼠标穿透

桌面组件要「能拖动、能置顶、还能一键穿透」。Tauri 的 set_ignore_cursor_events 与 set_always_on_top 解决大部分问题,但穿透和窗口层级必须成对切换,否则会出现「鼠标穿透了,窗口却被别的程序盖住」:

rust 复制代码
pub fn apply_clickthrough(window: &WebviewWindow, on: bool) -> Result<(), String> {
    window.set_ignore_cursor_events(on)?;
    window.set_always_on_top(on)?;
    set_top_band(window, on); // SetWindowPos:HWND_TOPMOST / HWND_NOTOPMOST 落实 Z 序
    Ok(())
}

3. 单文件打包

tauri build --no-bundle 直接出单 exe(当前 release 约 8 MB,实测 8.63 MB),不做安装包。好处是拷贝即用、数据可走便携模式;代价是仍依赖系统的 WebView2 运行时,严格说不是「完全零依赖」。

4. 本地数据 + AI 安全边界

日程、待办、便签全落 SQLite;删除先进回收站(30 天可恢复);提醒与重复日程在后台处理,面板关了提醒也不丢。

AI 不做中转服务:Rust 侧直接请求用户配置的服务商;写日程、删数据、执行命令的 tool call 都要二次确认,文件操作限定在工作目录。

私人秘书从「会聊天」到「能干活」

  • 技能调用 :工作区 skills/ 放技能说明,输入 / 弹出技能菜单(↑↓ 选择、Enter/Tab 插入、Esc 关闭),选中后注入 system prompt。
  • 快捷键 :Ctrl+Alt+A 随时打开 / 聚焦私人秘书,可在设置里改;与其他快捷键冲突自动跳过。
  • 检查点撤销:写日程 / 待办前自动快照,回复下方可一键撤销,恢复被删 / 被改的记录。
  • 只读研究员:只查日程、待办、日迹与空闲,不提供写工具------权限边界做成了独立智能体。
  • 记忆:全局 / 会话记忆可写入、遗忘、召回;计划模式禁止写记忆。
  • 能力诊断:测试连接真实探测流式与 tool calling,逐项显示通过 / 失败原因,不把「连上了但 tool 不行」误判为整体可用。
  • 协议兼容:OpenAI / Anthropic / Responses 的 usage 统一归一;支持 OpenCode Zen/Go 预设。

踩坑记录

  • 任务栏不是稳定 API:Win10 / Win11 的 UIA 树结构不同,Windows 更新也可能改细节,必须多级兜底 + 可观测日志。
  • 多屏 + DPI:不能只在启动时算一次坐标,显示器切换、缩放变化后都要重新定位。
  • WebView2 依赖:Win11 和装过 Edge 的机器一般没问题,干净 Win10 要单独处理。
  • 代码签名:个人项目没买证书,首次运行可能遇到 SmartScreen「未知发布者」,README 里已写核对方式。
  • Tauri vs Electron:Tauri 体积小,但 WebView2 版本差异、Windows 特有能力的坑要自己补;选 Tauri 是因为不想为一个日历塞一个完整 Chromium。

下载与交流