news-classifier/client/src/components/TitleBar.vue

171 lines
3.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { Minus, Square, Maximize2, X } from 'lucide-vue-next'
const appWindow = getCurrentWindow()
const isMaximized = ref(false)
const isDark = ref(false)
// 检查主题
const checkTheme = () => {
isDark.value = document.documentElement.classList.contains('dark')
}
// 检查窗口是否最大化
const checkMaximized = async () => {
try {
isMaximized.value = await appWindow.isMaximized()
} catch (error) {
console.error('Failed to check maximized state:', error)
}
}
onMounted(() => {
checkMaximized()
checkTheme()
// 监听主题变化
const observer = new MutationObserver(() => {
checkTheme()
})
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
})
})
// 最小化窗口
const minimize = async () => {
try {
await appWindow.minimize()
} catch (error) {
console.error('Failed to minimize:', error)
}
}
// 最大化/还原窗口
const toggleMaximize = async () => {
try {
await appWindow.toggleMaximize()
await checkMaximized()
} catch (error) {
console.error('Failed to toggle maximize:', error)
}
}
// 关闭窗口
const close = async () => {
try {
await appWindow.close()
} catch (error) {
console.error('Failed to close:', error)
}
}
</script>
<template>
<!-- data-tauri-drag-region: Tauri 自动处理窗口拖拽 -->
<div
data-tauri-drag-region
class="titlebar h-10 flex items-center justify-between px-3 select-none fixed top-0 left-0 right-0 z-50"
:class="{ 'titlebar-dark': isDark }"
>
<!-- 左侧标题 -->
<div data-tauri-drag-region class="flex items-center gap-2 pointer-events-none">
<div class="titlebar-icon" :class="{ 'titlebar-icon-dark': isDark }" />
<span class="titlebar-text">News Classifier</span>
</div>
<!-- 右侧窗口控制按钮 -->
<div class="flex items-center">
<!-- 最小化按钮 -->
<button
@click="minimize"
class="titlebar-btn"
title="最小化"
>
<Minus :size="14" />
</button>
<!-- 最大化/还原按钮 -->
<button
@click="toggleMaximize"
class="titlebar-btn"
:title="isMaximized ? '还原' : '最大化'"
>
<Square v-if="isMaximized" :size="12" />
<Maximize2 v-else :size="14" />
</button>
<!-- 关闭按钮 -->
<button
@click="close"
class="titlebar-btn titlebar-btn-close"
title="关闭"
>
<X :size="14" />
</button>
</div>
</div>
</template>
<style scoped>
.titlebar {
background: hsl(var(--card));
border-bottom: 1px solid hsl(var(--border));
}
.titlebar-dark {
background: hsl(var(--sidebar));
border-bottom: 1px solid hsl(var(--sidebar-border));
}
.titlebar-icon {
width: 12px;
height: 12px;
background: hsl(var(--primary));
border-radius: 2px;
}
.titlebar-icon-dark {
background: hsl(var(--sidebar-primary));
}
.titlebar-text {
font-size: 0.8125rem;
font-weight: 500;
color: hsl(var(--foreground));
}
.titlebar-btn {
padding: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
color: hsl(var(--muted-foreground));
background: transparent;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background 0.15s ease, color 0.15s ease;
}
.titlebar-btn:hover {
background: hsl(var(--accent));
color: hsl(var(--foreground));
}
.titlebar-btn-close:hover {
background: hsl(var(--destructive));
color: hsl(var(--destructive-foreground));
}
/* 防止拖拽时选中文本 */
.titlebar * {
user-select: none;
-webkit-user-select: none;
}
</style>