Tauri2 自定义窗口控制功能实战:Gisvip地图下载器窗口控制实现

Tauri   2026-02-05 16:56   4   0  

在开发 Gisvip 地图下载器的过程中,由于项目需求隐藏了系统自带的最大化、最小化和关闭应用按钮,我们在 src\layout\components\Header.vue 文件中重新设计并实现了这三个控制按钮的功能。本文将详细拆解 Tauri 中自定义窗口控制的创建、配置与功能实现,分享从基础用法到完整实战的全过程。

一、核心依赖与基础概念

Tauri 提供了 @tauri-apps/api/window 模块用于实现窗口控制,核心函数为 getCurrentWindow();搭配 @tauri-apps/plugin-process 可实现应用退出功能,element-plus 则用于构建 UI 界面。

权限配置注意:由于我们隐藏了系统默认的窗口控制按钮,需要在 src-tauri\capabilities\default.json 中添加相应的权限,以允许应用执行最大化、最小化、关闭等操作。

二、基础配置

1. 配置窗口权限

src-tauri\capabilities\default.json 中添加以下权限:

"permissions": [
  "core:window:allow-maximize",
  "core:window:allow-minimize",
  "core:window:allow-unminimize",
  "core:window:allow-unmaximize",
  "core:window:allow-close",
  "core:window:allow-start-dragging"
]

2. 隐藏系统默认窗口控制按钮

src-tauri\tauri.conf.json 中设置 app/windows/decorationsfalse

{
  "app": {
    "windows": [
      {
        "decorations": false
      }
    ]
  }
}

3. 给头部加上拖拽样式,使窗口可拖动

src\layout\components\Header.vue 中添加以下样式:

.header-container {
  position: relative;
  height: 30px;
  display: flex;
  -webkit-app-region: drag;
}

三、完整实战:自定义窗口控制实现

以下是 Gisvip 地图下载器中自定义窗口控制的完整实现代码,包含「最小化」「最大化/还原」「关闭」核心功能,以及窗口拖拽的完整逻辑:

1. 核心组件实现(Header.vue)

<template>
  <div class="header-container">
    <div class="left-container"></div>
    <div class="right-container">
      <el-button class="minimize" text plain icon="SemiSelect" @click="minimize" />
      <el-button class="maximize" text plain @click="toggleMaximize">
        <svg-icon v-if="isMaximized" icon-class="minimize" class="svg-icon" />
        <svg-icon v-else icon-class="maximize" class="svg-icon"/>
      </el-button>
      <el-button class="closeapp" text plain icon="CloseBold" @click.stop="close" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { getCurrentWindow } from '@tauri-apps/api/window';
import { ElMessageBox } from 'element-plus'

const appWindow = getCurrentWindow();
const isMaximized = ref(false)

// 最小化窗口
const minimize = async () => {
  await appWindow.minimize()
}

// 最大化窗口
const maximize = async () => {
  await appWindow.maximize()
  isMaximized.value = true
}

// 还原窗口
const unmaximize = async () => {
  await appWindow.unmaximize()
  isMaximized.value = false
}

// 切换最大化/还原状态
const toggleMaximize = async () => {
  isMaximized.value = await appWindow.isMaximized()
  if (isMaximized.value) {
    await unmaximize()
  } else {
    await maximize()
  }
}

// 关闭应用
const close = async () => {
  ElMessageBox.confirm(
    '确定要关闭应用吗?',
    '提示',
    {
      confirmButtonText: '确 定',
      cancelButtonText: '取 消',
      type: 'warning'
    }
  ).then(() => {
    try {
      exitApp()
    } catch (error) {
      appWindow.close()
    }
  }).catch(() => {})
}
</script>
<style scoped>
.header-container {
  position: relative;
  height: 30px;
  display: flex;
  -webkit-app-region: drag;
}


博客评论