最近把自用的 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。