截图模块初始化

This commit is contained in:
zhongluofeng
2026-07-31 18:30:55 +08:00
parent 9d8f963cc6
commit 66575c6166
16 changed files with 1011 additions and 481 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ defineProps<{
class="flex-1"
:style="{ backgroundColor: 'var(--effect-bg)', backdropFilter: 'var(--effect-blur)' }"
>
<ScrollArea class="h-full w-full">
<ScrollArea data-main-scroll class="h-full w-full">
<Transition name="fade-slide" mode="out-in">
<div
v-if="activeComponent"
+80 -20
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { Search, Settings, ChevronRight } from '@lucide/vue'
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { Search, Settings, ChevronRight, ArrowUp } from '@lucide/vue'
import { Input } from '@/components/ui/input'
import { invoke } from '@tauri-apps/api/core'
import { getCurrentWindow } from '@tauri-apps/api/window'
@@ -137,6 +137,48 @@ if (tauriWindow) {
// 初始时窗口已显示,恢复 hover
restoreHover(300)
// ===== 回到顶部按钮 =====
const showScrollTop = ref(false)
let scrollViewport: HTMLElement | null = null
let rafId: number | null = null
const handleMainScroll = () => {
if (!scrollViewport) return
showScrollTop.value = scrollViewport.scrollTop > 200
}
const scrollToTop = () => {
if (!scrollViewport) return
const start = scrollViewport.scrollTop
if (start === 0) return
// 物理变速滚动:cubic ease-out,先快后慢
const duration = 500
const startTime = performance.now()
const easeOutCubic = (t: number) => 1 - Math.pow(1 - t, 3)
if (rafId !== null) cancelAnimationFrame(rafId)
const animate = (now: number) => {
const elapsed = now - startTime
const progress = Math.min(elapsed / duration, 1)
scrollViewport!.scrollTop = start * (1 - easeOutCubic(progress))
if (progress < 1) {
rafId = requestAnimationFrame(animate)
} else {
rafId = null
}
}
rafId = requestAnimationFrame(animate)
}
const initScrollListener = () => {
scrollViewport = document.querySelector<HTMLElement>(
'[data-main-scroll] [data-reka-scroll-area-viewport]'
)
if (scrollViewport) {
scrollViewport.addEventListener('scroll', handleMainScroll, { passive: true })
handleMainScroll()
}
}
onMounted(async () => {
if (tauriWindow) {
try {
@@ -152,12 +194,16 @@ onMounted(async () => {
invoke('fix_snap_background').catch(() => {})
}, 1000)
}
// 等待模块容器渲染后绑定滚动监听
nextTick(initScrollListener)
})
onUnmounted(() => {
window.removeEventListener('mousemove', handleFirstMouseMove)
if (restoreHoverTimer) clearTimeout(restoreHoverTimer)
if (unlistenMaximize) unlistenMaximize()
if (scrollViewport) scrollViewport.removeEventListener('scroll', handleMainScroll)
if (rafId !== null) cancelAnimationFrame(rafId)
})
const handleBlur = () => {
@@ -178,28 +224,41 @@ const handleBlur = () => {
>
<span class="font-semibold text-sm">Thing</span>
<!-- 浮动标签切换器模块内 TabsList 滚出可视区时显示 -->
<Transition name="floating-tabs">
<div
v-if="tabsStore.floatingVisible && tabsStore.tabs.length > 0"
class="flex items-center gap-0.5 ml-2 pointer-events-auto"
>
<!-- 浮动标签切换器 + 回到顶部按钮 -->
<div class="flex items-center gap-1 ml-2 pointer-events-auto">
<Transition name="floating-tabs">
<div
v-if="tabsStore.floatingVisible && tabsStore.tabs.length > 0"
class="flex items-center gap-0.5"
>
<button
v-for="tab in tabsStore.tabs"
:key="tab.value"
class="px-2.5 py-1 text-xs font-medium rounded-md transition-colors"
:class="
tabsStore.activeTab === tab.value
? 'bg-primary text-primary-foreground'
: 'text-muted-foreground hover:text-foreground hover:bg-secondary/60'
"
@click="tabsStore.setActiveTab(tab.value)"
@mousedown.stop
>
{{ tab.label }}
</button>
</div>
</Transition>
<Transition name="floating-tabs">
<button
v-for="tab in tabsStore.tabs"
:key="tab.value"
class="px-2.5 py-1 text-xs font-medium rounded-md transition-colors"
:class="
tabsStore.activeTab === tab.value
? 'bg-primary text-primary-foreground'
: 'text-muted-foreground hover:text-foreground hover:bg-secondary/60'
"
@click="tabsStore.setActiveTab(tab.value)"
v-if="showScrollTop"
class="flex items-center justify-center h-6 w-6 rounded-md text-muted-foreground hover:text-foreground hover:bg-secondary/60 transition-colors"
title="回到顶部"
@click="scrollToTop"
@mousedown.stop
>
{{ tab.label }}
<ArrowUp class="h-3.5 w-3.5" />
</button>
</div>
</Transition>
</Transition>
</div>
<div class="flex-1"></div>
<div class="relative max-w-xs mr-3 pointer-events-auto">
@@ -310,6 +369,7 @@ const handleBlur = () => {
.hover-suppressed button:hover,
.hover-suppressed button.is-hovered {
background-color: transparent !important;
color: var(--foreground) !important;
}
/* 最大化按钮:snap-layout 插件的原生子窗口遮挡了指针事件,