Write the Code. Change the World.

11月 26

自古以来,对于桌面应用,系统托盘是不可缺少的一部分。tauri 2 也是一样。

官网文档:https://v2.tauri.app/learn/system-tray/
参考博客:https://blog.csdn.net/xiaoyuanbaobao/article/details/143781484

对于 tarui 2,很多服务端的功能,前端也可以实现。它会提供一套 api,使得前端可以构建服务端的能力。当然,也可以在服务端去实现,然后用前端去调用。

简单记录一下

有上边的文档和博客,就可以完成基础的托盘创建。这里做以下简单的记录。

  1. src-tauri/Cargo.toml 中修改配置 tauri = { version = "2", features = ["tray-icon", "image-png"] }。 这里增加了一个 image-png 配置。

2.后边如果运行报错。 error: failed to select a version for the requirement image = "^0.25" candidate versions found which didn't match: 0.24.7, 0.24.6, 0.24.5, ...
location searched: crates.io index
时,就在 src-tauri/Cargo.toml 中追加配置。

[dependencies]
image = "^0.25"
tauri = { version = "2", features = ["tray-icon", "image-png"] }

3.权限设置。系统托盘往往会操作窗体的显示和程序的退出。这些都需要配置权限。在 src-tauri/capabilities/default.json 中,增加以下配置。

    "core:window:allow-set-focus",
    "core:window:allow-close",
    "core:window:allow-is-visible",
    "core:window:allow-unmaximize",
    "core:window:allow-unminimize",
    "core:window:allow-minimize"

加上之前的,完整的 default.json 文件长这样。

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "Capability for the main window",
  "windows": [
    "main"
  ],
  "permissions": [
    "core:default",
    "shell:allow-open",
    {
      "identifier": "http:default",
      "allow": [
        {
          "url": "http://digitalai.dabaoensi.com:8181/"
        },
        {
          "url": "https://www.yuepaibao.com/"
        }
      ],
      "deny": [
        {
          "url": "https://private.tauri.app"
        }
      ]
    },
    "core:webview:allow-create-webview",
    "core:window:allow-show",
    "core:window:allow-set-fullscreen",
    "core:webview:allow-create-webview-window",
    "core:webview:allow-webview-close",
    "process:default",
    "core:window:allow-set-focus",
    "core:window:allow-close",
    "core:window:allow-is-visible",
    "core:window:allow-unmaximize",
    "core:window:allow-unminimize",
    "core:window:allow-minimize"
  ]
}

上边这些配置好了。就开始写代码了。

创建 src/utils/tray.ts 文件。把上边博客中的代码复制过来。

// 获取当前窗口
import { getCurrentWindow } from '@tauri-apps/api/window';
// 导入系统托盘
import { TrayIcon, TrayIconOptions, TrayIconEvent } from '@tauri-apps/api/tray';
// 托盘菜单
import { Menu, MenuOptions } from '@tauri-apps/api/menu';
// 进程管理
import { exit } from '@tauri-apps/plugin-process';

/**
 * 在这里你可以添加一个托盘菜单,标题,工具提示,事件处理程序等
 */
const options: TrayIconOptions = {
    // icon 的相对路径基于:项目根目录/src-tauri/,其他 tauri api 相对路径大抵都是这个套路
    icon: "icons/32x32.png",
    // 托盘提示,悬浮在托盘图标上可以显示 tauri-app
    tooltip: '大报恩寺',
    // 是否在左键点击时显示托盘菜单,默认为 true。当然不能为 true 啦,程序进入后台不得左键点击图标显示窗口啊。
    menuOnLeftClick: false,
    // 托盘图标上事件的处理程序。
    action: (event: TrayIconEvent) => {
        // 左键点击事件
        if (event.type === 'Click' && event.button === "Left" && event.buttonState === 'Down') {
            console.log('单击事件');
            // 显示窗口
            winShowFocus();
        }
    }
}

/**
 * 窗口置顶显示
 */
async function winShowFocus() {
    // 获取窗体实例
    const win = getCurrentWindow();
    // 检查窗口是否见,如果不可见则显示出来
    if (!(await win.isVisible())) {
        win.show();
    } else {
        // 检查是否处于最小化状态,如果处于最小化状态则解除最小化
        if (await win.isMinimized()) {
            await win.unminimize();
        }
        // 窗口置顶
        await win.setFocus();
    }
}

/**
 * 创建托盘菜单
 */
async function createMenu() {
    return await Menu.new({
        // items 的显示顺序是倒过来的
        items: [
            {
                id: 'show',
                text: '显示窗口',
                action: () => {
                    winShowFocus();
                }
            },
            {
                // 菜单 id
                id: 'quit',
                // 菜单文本
                text: '退出',
                //  菜单项点击事件
                action: () => {
                    console.log('退出')
                    // 退出应用
                    exit(0);
                }
            }
        ]
    })
}

/**
 * 创建系统托盘
 */
export async function createTray() {
    // 获取 menu
    options.menu = await createMenu();
    await TrayIcon.new(options);
}

然后,就是使用了。 在 App.vue 中。增加以下代码。

<script setup lang="ts">
import { createTray } from './utils/tray'

createTray()
  .then(() => {
    console.log("sucess");
  })
  .catch((error: any) => {
    console.log("error", error);
  });

</script>

最后执行 pnpm tauri dev 来运行,试试效果。如果一切正常,表示是 ok。如果有问题,遇到问题就要解决问题,直到成功为止。

零代码托盘

可以直接在 src-tauri/tauri.conf.json 中增加配置,来实现托盘。只是这个托盘仅仅是个托盘,没有任何交互和右键菜单。追加配置如下:

{
  "app": {
    "windows": [
      {
        "title": "南京大报恩寺",
        "width": 540,
        "height": 960
      }
    ],
    "security": {
      "csp": null
    },
    "trayIcon": {
      "iconPath": "icons/icon.png",
      "iconAsTemplate": true,
      "title": "大报恩寺",
      "tooltip": "大报恩寺"
    }
  },
}

就是在 app 节点下增加 trayIcon 配置即可。如果配置了这个,代码实现的托盘就无效了。

美观优化

好看的托盘菜单都会有 icon 和 文字一起组合构成,这样才更好看。看 MenuOptions 的 items。它的类型有 MenuItem, IconMenuItem 等构成。其中 IconMenuItem 就是有 icon 的菜单。

    /** List of items to add to the new menu. */
    items?: Array<Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions>;

https://www.iconfont.cn 中,找一个适合的 icon,以 png 格式下载下来。宽高 32*32 就可以。文件放在 src-tauri/assets/image/tray/exit.png 这里。修改原来的 tray.ts 代码。

            {
                // 菜单 id
                id: 'quit',
                // 菜单文本
                text: '退出',
                icon: 'assets/image/tray/exit.png',
                //  菜单项点击事件
                action: () => {
                    console.log('退出')
                    // 退出应用
                    exit(0);
                }
            }

就是增加了一个 icon,属性,配置好图片路径就可以。

对应 ts 类型

https://v2.tauri.app/reference/javascript/api/namespacetray/#new

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注