在开发 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 中添加相应的权限,以允许应用执行最大化、最小化、关闭等操作。
在 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" ]
在 src-tauri\tauri.conf.json 中设置 app/windows/decorations 为 false:
{
"app": {
"windows": [
{
"decorations": false
}
]
}
}
在 src\layout\components\Header.vue 中添加以下样式:
.header-container {
position: relative;
height: 30px;
display: flex;
-webkit-app-region: drag;
}
以下是 Gisvip 地图下载器中自定义窗口控制的完整实现代码,包含「最小化」「最大化/还原」「关闭」核心功能,以及窗口拖拽的完整逻辑:
<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;
}