在开发 Gisvip 地图下载器的过程中,用户可通过托盘快速唤起窗口或退出程序。本文将详细拆解 Tauri 中系统托盘的创建、配置与功能实现,分享从基础用法到完整实战的全过程。
Tauri 提供了 @tauri-apps/api/tray 模块用于实现系统托盘,核心类为 TrayIcon;搭配 @tauri-apps/api/menu 可实现托盘右键菜单,@tauri-apps/api/window 则用于窗口状态的控制(显示、置顶、解除最小化等)。
路径规则注意:托盘图标 icon 的相对路径基于项目根目录下的 src-tauri/ 文件夹,这是 Tauri 各类资源路径的通用规则。
先实现最简易的托盘创建,仅初始化托盘实例,后续可逐步扩展配置:
import { TrayIcon } from '@tauri-apps/api/tray';
const options = {
// 可在此配置图标、菜单、事件等核心参数
};
const tray = await TrayIcon.new(options);
为托盘设置自定义图标,只需在 options 中指定 icon 路径,替换为自己的图标文件即可:
import { TrayIcon } from '@tauri-apps/api/tray';
const options = {
icon: "icons/32x32.png", // 路径基于 src-tauri/
};
const tray = await TrayIcon.new(options);
通过 Menu 类创建右键菜单,可自定义菜单项的文本、点击事件,同时控制左键点击是否触发菜单:
import { TrayIcon } from '@tauri-apps/api/tray';
import { Menu } from '@tauri-apps/api/menu';
// 创建右键菜单
const menu = await Menu.new({
items: [
{
id: 'quit',
text: '退出',
action: () => {
console.log('quit pressed');
},
},
],
});
const options = {
menu,
menuOnLeftClick: false, // 禁用左键显示菜单(默认true,左键/右键均触发)
};
const tray = await TrayIcon.new(options);
以下是 Gisvip 地图下载器中托盘的完整实现代码,包含「显示窗口」「退出程序」核心功能,以及左键唤起窗口、右键菜单的完整逻辑:
// 获取当前窗口
import { getCurrentWindow } from '@tauri-apps/api/window';
// 导入系统托盘相关
import { TrayIcon, TrayIconOptions, TrayIconEvent } from '@tauri-apps/api/tray';
// 托盘菜单
import { Menu } from '@tauri-apps/api/menu';
import { getName } from '@tauri-apps/api/app';
/**
* 窗口置顶并显示(处理隐藏/最小化状态)
*/
const winShowFocus = async () => {
const win = getCurrentWindow();
// 窗口不可见则显示
if (!(await win.isVisible())) {
win.show();
} else {
// 最小化则解除最小化
if (await win.isMinimized()) {
await win.unminimize();
}
// 窗口置顶聚焦
await win.setFocus();
}
};
/**
* 创建托盘右键菜单
*/
const createMenu = async () => {
return await Menu.new({
items: [
{
icon: 'icons/32x32.png',
id: 'show',
text: '显示窗口',
action: () => {
winShowFocus();
},
},
{
id: 'quit',
text: '退出',
action: async () => {
try {
await getCurrentWindow().close(); // 关闭窗口并退出程序
} catch (error) {
console.error('退出程序失败:', error);
}
},
},
],
});
};
/**
* 初始化系统托盘
*/
export const createTray = async () => {
const options: TrayIconOptions = {
// 托盘图标(路径基于 src-tauri/)
icon: 'icons/32x32.png',
// 悬浮提示文本(获取应用名称)
tooltip: await getName(),
// 禁用左键显示菜单(左键用于唤起窗口)
menuOnLeftClick: false,
// 托盘图标事件处理
action: (event: TrayIconEvent) => {
// 监听左键按下事件
if (event.type === 'Click' && event.button === 'Left' && event.buttonState === 'Down') {
winShowFocus(); // 唤起并置顶窗口
}
},
};
// 挂载右键菜单
options.menu = await createMenu();
// 创建托盘实例
await TrayIcon.new(options);
};
在 Vue 组件(如 App.vue)的挂载阶段调用 createTray,完成托盘初始化:
<script setup lang="ts">
import { onMounted } from 'vue';
import { createTray } from './utils/tray'; // 引入封装的托盘函数
onMounted(() => {
createTray()
.then(() => {
console.log('系统托盘创建成功');
})
.catch((error) => {
console.error('托盘创建失败:', error);
});
});
</script>