chore: 发布v5.2.1版本并优化布局交互

1. 调整AppGrid和主容器的高度样式,替换calc(100vh - 140px)为100%适配布局
2. 为下载队列添加滚轮隐藏/显示动画和交互逻辑
3. 优化主内容区域的flex布局结构,修复滚动和容器收缩问题
This commit is contained in:
2026-07-17 21:12:50 +08:00
parent 61f5cc954c
commit 37217cd6fb
4 changed files with 52 additions and 24 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "spark-store", "name": "spark-store",
"version": "5.2.0", "version": "5.2.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "spark-store", "name": "spark-store",
"version": "5.2.0", "version": "5.2.1",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",
+7 -6
View File
@@ -45,9 +45,9 @@
/> />
</aside> </aside>
<main class="h-full min-h-0 flex-1"> <main class="flex h-full min-h-0 flex-1 flex-col">
<div <div
class="sticky top-10 z-30 border-b border-slate-200/70 bg-slate-50 px-4 py-4 lg:px-10 dark:border-slate-800/70 dark:bg-slate-950" class="sticky top-10 z-30 shrink-0 border-b border-slate-200/70 bg-slate-50 px-4 py-4 lg:px-10 dark:border-slate-800/70 dark:bg-slate-950"
> >
<AppHeader <AppHeader
:search-query="searchQuery" :search-query="searchQuery"
@@ -67,12 +67,13 @@
activeTab !== 'home' && activeTab !== 'home' &&
Object.keys(displayCategories).length > 0 Object.keys(displayCategories).length > 0
" "
class="shrink-0"
:categories="displayCategories" :categories="displayCategories"
:selected-category="selectedCategory" :selected-category="selectedCategory"
:category-counts="categoryCounts" :category-counts="categoryCounts"
@select-category="selectSubCategory" @select-category="selectSubCategory"
/> />
<div class="px-4 py-6 lg:px-10"> <div class="flex min-h-0 flex-1 flex-col px-4 py-6 lg:px-10">
<FavoriteFolderManager <FavoriteFolderManager
v-if="currentView === 'favorites'" v-if="currentView === 'favorites'"
:folders="favoriteFolders" :folders="favoriteFolders"
@@ -87,9 +88,7 @@
@open-detail="openDetail" @open-detail="openDetail"
/> />
<template v-else-if="activeTab === 'home'"> <template v-else-if="activeTab === 'home'">
<div <div class="h-full overflow-y-auto pr-2 scrollbar-nowidth">
class="max-h-[calc(100vh-8rem)] overflow-y-auto pr-2 scrollbar-nowidth"
>
<HomeView <HomeView
:links="homeLinks" :links="homeLinks"
:loading="homeLoading" :loading="homeLoading"
@@ -99,6 +98,7 @@
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div class="min-h-0 flex-1">
<AppGrid <AppGrid
:apps="filteredApps" :apps="filteredApps"
:loading="effectiveLoading" :loading="effectiveLoading"
@@ -107,6 +107,7 @@
:show-origin="storeFilter === 'both' && !isHomeListTab" :show-origin="storeFilter === 'both' && !isHomeListTab"
@open-detail="handleAppCardOpenDetail" @open-detail="handleAppCardOpenDetail"
/> />
</div>
</template> </template>
</div> </div>
</main> </main>
+3 -6
View File
@@ -18,10 +18,7 @@
</div> </div>
<!-- 应用数量较少时使用普通网格带滚动 --> <!-- 应用数量较少时使用普通网格带滚动 -->
<div <div v-else-if="!loading && apps.length <= 50" class="non-virtual-scroller">
v-else-if="!loading && apps.length <= 50"
class="non-virtual-scroller"
>
<div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4"> <div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
<AppCard <AppCard
v-for="(app, index) in apps" v-for="(app, index) in apps"
@@ -176,14 +173,14 @@ const gridRows = computed(() => {
<style scoped> <style scoped>
.scroller { .scroller {
height: calc(100vh - 140px); /* 调整高度 */ height: 100%;
overflow-y: auto; overflow-y: auto;
padding: 0; /* 移除内边距 */ padding: 0; /* 移除内边距 */
margin: -24px -16px; /* 抵消父容器的 px-4 py-6 */ margin: -24px -16px; /* 抵消父容器的 px-4 py-6 */
} }
.non-virtual-scroller { .non-virtual-scroller {
height: calc(100vh - 140px); height: 100%;
overflow-y: auto; overflow-y: auto;
} }
+32 -2
View File
@@ -1,6 +1,12 @@
<template> <template>
<div <div
class="fixed inset-x-4 bottom-4 z-40 rounded-3xl border border-slate-200/70 bg-white shadow-2xl dark:border-slate-800/70 dark:bg-slate-900 sm:left-auto sm:right-6 sm:w-96" ref="queueRef"
class="fixed inset-x-4 bottom-4 z-40 rounded-3xl border border-slate-200/70 bg-white shadow-2xl transition-all duration-200 dark:border-slate-800/70 dark:bg-slate-900 sm:left-auto sm:right-6 sm:w-96"
:class="
isHidden
? 'pointer-events-none translate-y-[calc(100%+1rem)] opacity-0'
: 'translate-y-0 opacity-100'
"
> >
<div <div
class="flex items-center justify-between px-5 py-4" class="flex items-center justify-between px-5 py-4"
@@ -130,7 +136,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from "vue"; import { computed, onMounted, onUnmounted, ref } from "vue";
import type { DownloadItem } from "../global/typedefinition"; import type { DownloadItem } from "../global/typedefinition";
const props = defineProps<{ const props = defineProps<{
@@ -147,6 +153,30 @@ const emit = defineEmits<{
}>(); }>();
const isExpanded = ref(false); const isExpanded = ref(false);
const isHidden = ref(false);
const queueRef = ref<HTMLElement | null>(null);
const onWheel = (event: WheelEvent) => {
if (queueRef.value?.contains(event.target as Node) || event.deltaY === 0) {
return;
}
if (event.deltaY > 0) {
isExpanded.value = false;
isHidden.value = true;
return;
}
isHidden.value = false;
};
onMounted(() => {
document.addEventListener("wheel", onWheel, { passive: true, capture: true });
});
onUnmounted(() => {
document.removeEventListener("wheel", onWheel, { capture: true });
});
const completedDownloads = computed(() => { const completedDownloads = computed(() => {
return props.downloads.filter((d) => d.status === "completed").length; return props.downloads.filter((d) => d.status === "completed").length;