背景
近期,我基于自研的个人时间管理 Web 应用 「时光助手」,借助 AI 辅助开发,通过 Tauri 框架完成了 Windows 客户端的打包工作。初次体验 Tauri 便收获了不错的反馈 ------ 其生成的客户端体积轻量化、运行性能优异,且与 Web 端的适配性远超预期。
不过,从 Web 应用到桌面客户端的迁移,并非简单的 "打包封装" 就能一蹴而就,目前仍有不少细节有待打磨。后续我计划从两个维度深耕:一是系统性吃透 Tauri 框架的底层逻辑与进阶用法;二是对 AI 生成的代码进行全面人工复核。毕竟 AI 生成的代码存在两个明显痛点:部分逻辑的实现原理模糊不清,可能暗藏隐患或冗余;再加上各类功能框架与组件版本差异显著、官方文档覆盖不全,AI 受限于底层机制产生的 "幻觉" 问题会被进一步放大。唯有人工逐行校验,才能让代码真正稳定可靠。
鼠标左键点击托盘图标,不弹出菜单
应用最小化到托盘后,用户如想显示主窗口或退出,通过右键托盘图标,弹出菜单实现的,当前的问题在于,用户点击鼠标左键,也会弹出菜单,需要屏蔽掉左键菜单。
依然使用 TRAE,将需求告知 ,如下:
rust
tauri框架生成的客户端,当最小化托盘图标时,鼠标左键单击不要显示菜单,而是显示主窗口
AI 处理完后,发现代码没变化,细看发现 AI 居然跳出了原先的项目结构,新建了一个目录和文件,比较无语,如下:
rust
/e/dev/meet/platform-web/src-tauri/src/lib.rs
明确告诉它搞错了,正确的位置是E:\dev\meet\platform-web\src-tauri\src,才对项目内应该修改的源码进行调整,看代码逻辑,监控了托盘图标的点击事件,如果判断是鼠标左键单击,则显示主窗口,代码如下:
rust
// 修改托盘图标配置部分,完整替换以下代码:
// 5. 创建系统托盘
let _tray = TrayIconBuilder::new()
.icon(app.default_window_icon().unwrap().clone())
.tooltip("时光助手")
.menu(&tray_menu)
// 处理托盘图标点击事件 - 左键单击显示主窗口
.on_tray_icon_event(|tray, event| {
match event {
TrayIconEvent::Click { button, .. } => {
// 只处理左键单击
if button == tauri::MouseButton::Left {
let app_handle = tray.app_handle();
// 获取窗口并显示
if let Some(window) = app_handle.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
}
TrayIconEvent::DoubleClick { .. } => {
let app_handle = tray.app_handle();
// 获取窗口并显示
if let Some(window) = app_handle.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
_ => {}
}
})
// 处理菜单点击事件
.on_menu_event(|tray, event| {
let app_handle = tray.app_handle();
match event.id().as_ref() {
"show_window" => {
if let Some(window) = app_handle.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
"quit_app" => {
// 退出应用
app_handle.exit(0);
}
_ => {}
}
})
.build(app)?;
结果,打包的时候提示编译错误......
rust
Compiling tauri-plugin v2.5.2
Compiling tauri-codegen v2.5.2
Info File src-tauri\src\lib.rs changed. Rebuilding application...
Compiling tauri-utils v2.8.1
Compiling windows v0.61.3
Compiling tauri-build v2.5.3
Compiling tauri-plugin v2.5.2
Compiling tauri-codegen v2.5.2
Compiling tauri v2.9.5
Compiling tauri-macros v2.5.2
Compiling tauri-plugin-os v2.3.2
Compiling tauri-plugin-notification v2.3.3
Compiling TimeHelper v3.4.0 (E:\dev\meet\platform-web\src-tauri)
Compiling webview2-com-sys v0.38.0
Compiling tao v0.34.5
Compiling tauri-winrt-notification v0.7.2
Compiling notify-rust v4.11.7
Compiling webview2-com v0.38.0
Info File src-tauri\tauri.conf.json changed. Rebuilding application...
Compiling windows v0.61.3
Compiling TimeHelper v3.4.0 (E:\dev\meet\platform-web\src-tauri)
Compiling webview2-com-sys v0.38.0
Compiling tao v0.34.5
Compiling tauri-winrt-notification v0.7.2
Compiling notify-rust v4.11.7
Compiling webview2-com v0.38.0
Compiling tauri-runtime v2.9.2
Compiling wry v0.53.5
Compiling tauri-runtime-wry v2.9.3
Compiling tauri v2.9.5
Compiling tauri-plugin-single-instance v2.3.6
Compiling tauri-plugin-notification v2.3.3
Compiling tauri-plugin-os v2.3.2
error[E0433]: failed to resolve: could not find `MouseButton` in `tauri`
--> src\lib.rs:66:49
|
66 | ... if button == tauri::MouseButton::Left {
| ^^^^^^^^^^^ could not find `MouseButton` in `tauri`
|
help: consider importing this enum
|
2 + use tauri::tray::MouseButton;
|
help: if you import `MouseButton`, refer to it directly
|
66 - if button == tauri::MouseButton::Left {
66 + if button == MouseButton::Left {
|
For more information about this error, try `rustc --explain E0433`.
把错误扔给 AI,AI 分析是包搞错了,如下:
rust
我看到编译过程中出现了错误,问题是找不到 MouseButton 类型。根据错误提示,MouseButton 应该来自 tauri::tray 模块,而不是直接在 tauri 根模块下。
然后导入了 tray 下的 MouseButton,结果代码使用还是 tauri 包下,又搞了一轮编译不通过,最终提供了一版编译无问题,代码如下:
rust
// 使用 Tauri 2.0 正确 API 实现所有功能
use tauri::{
menu::{MenuBuilder, MenuItemBuilder},
tray::{MouseButton, TrayIconBuilder, TrayIconEvent},
Manager,
};
use tauri_plugin_single_instance::init as single_instance_init;
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_notification::init())
.setup(|app| {
// 1. 初始化单实例插件
app.handle()
.plugin(single_instance_init(|app, _argv, _cwd| {
// 当新实例启动时,激活现有实例的窗口
if let Some(window) = app.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}))?;
// 2. 获取主窗口
let main_window = match app.get_webview_window("main") {
Some(window) => window,
None => {
eprintln!("主窗口(ID: main)未创建!");
return Ok(());
}
};
// 3. 监听窗口关闭事件
let window_clone = main_window.clone();
main_window.on_window_event(move |event| {
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
// 阻止默认关闭
api.prevent_close();
// 隐藏窗口
let _ = window_clone.hide();
}
});
// 4. 创建托盘菜单
let show_window_item = MenuItemBuilder::new("显示主窗口")
.id("show_window")
.build(app)?;
let quit_app_item = MenuItemBuilder::new("退出应用").id("quit_app").build(app)?;
let tray_menu = MenuBuilder::new(app)
.item(&show_window_item)
.item(&quit_app_item)
.build()?;
// 5. 创建系统托盘
let _tray = TrayIconBuilder::new()
.icon(app.default_window_icon().unwrap().clone())
.tooltip("时光助手")
.menu(&tray_menu)
// 处理托盘点击事件 - 修改这里!
.on_tray_icon_event(|tray, event| {
match event {
// 添加左键单击事件处理
TrayIconEvent::Click { button, .. } => {
if button == MouseButton::Left {
let app_handle = tray.app_handle();
// 获取窗口并显示
if let Some(window) = app_handle.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
}
// 保持双击事件处理不变
TrayIconEvent::DoubleClick { .. } => {
let app_handle = tray.app_handle();
// 获取窗口并显示
if let Some(window) = app_handle.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
_ => {}
}
})
// 处理菜单点击事件
.on_menu_event(|tray, event| {
let app_handle = tray.app_handle();
match event.id().as_ref() {
"show_window" => {
if let Some(window) = app_handle.get_webview_window("main") {
let _ = window.show();
let _ = window.set_focus();
}
}
"quit_app" => {
// 退出应用
app_handle.exit(0);
}
_ => {}
}
})
.build(app)?;
Ok(())
})
.run(tauri::generate_context!())
.expect("运行 Tauri 应用失败");
}
但是,经测试,发现还是有问题,左键点击依然会弹出菜单,快速闪烁一下后消失......
代码逻辑看上去一切正常,于是只能开启人工诊断模式。
去官网查看托盘功能相关文档:https://tauri.app/zh-cn/learn/system-tray/#创建托盘图标
发现官方有明确说明,默认情况下,确实单击左键会显示菜单,如下图:

按照官方说明,构建托盘的时候,设置一个属性menu_on_left_click就可以了。
手工修改,打包时提示警告,方法已过时......
rust
warning: use of deprecated method `tauri::tray::TrayIconBuilder::<R>::menu_on_left_click`: Use `TrayIconBuilder::show_menu_on_left_click` instead.
--> src\lib.rs:61:18
|
61 | .menu_on_left_click(false)
| ^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
功能测试倒是正常了,终于左键不再弹出菜单了。
根据警告的提示,将属性从已废弃的menu_on_left_click,调整为show_menu_on_left_click,编译也不再报警告了,测试功能也正常。
小结
看起来一个挺简单的小问题,AI 折腾了半小时,出现了多次错误,最终也没实现预期效果。人工查阅官方文档,10 分钟就完成了处理,当然也存在一定的运气成分,刚好这个问题,官方文档里有明确说明,从警告信息来看,官方文档也陈旧了......在这种局面下,AI 也难以给出准确的答案。