去除界面优化

This commit is contained in:
2026-03-15 17:00:58 +08:00
parent 74b1f65ab1
commit 6729e321a6
15 changed files with 141 additions and 227 deletions

View File

@@ -1,21 +1,16 @@
<template>
<div
class="flex min-h-screen flex-col text-slate-900 transition-colors duration-300 dark:text-slate-100 lg:flex-row bg-[#f8fafc] dark:bg-[#0f172a]"
class="flex min-h-screen flex-col bg-slate-50 text-slate-900 transition-colors duration-300 dark:bg-slate-950 dark:text-slate-100 lg:flex-row"
>
<!-- 背景装饰浅色下为极淡渐变深色下为 subtle grain -->
<div
class="pointer-events-none fixed inset-0 z-0 bg-gradient-to-br from-slate-50/80 via-transparent to-brand/[0.02] dark:from-slate-950/50 dark:to-transparent"
aria-hidden="true"
/>
<!-- 移动端侧边栏遮罩 -->
<div
v-if="isSidebarOpen"
class="fixed inset-0 z-40 bg-slate-900/30 backdrop-blur-md lg:hidden transition-opacity"
class="fixed inset-0 z-40 bg-black/20 backdrop-blur-sm lg:hidden"
@click="isSidebarOpen = false"
/>
></div>
<aside
class="fixed inset-y-0 left-0 z-50 w-72 transform border-r border-slate-200/60 bg-white/90 px-5 py-6 shadow-xl shadow-slate-200/20 backdrop-blur-xl transition-transform duration-300 ease-out dark:border-slate-800/50 dark:bg-slate-900/95 dark:shadow-none lg:sticky lg:top-0 lg:flex lg:h-screen lg:translate-x-0 lg:flex-col lg:border-b-0 lg:shadow-none"
class="fixed inset-y-0 left-0 z-50 w-72 transform border-r border-slate-200/70 bg-white/95 px-5 py-6 backdrop-blur transition-transform duration-300 ease-in-out dark:border-slate-800/70 dark:bg-slate-900 lg:sticky lg:top-0 lg:flex lg:h-screen lg:translate-x-0 lg:flex-col lg:border-b-0"
:class="
isSidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'
"
@@ -31,7 +26,7 @@
/>
</aside>
<main class="relative z-10 flex-1 px-4 py-6 lg:px-10">
<main class="flex-1 px-4 py-6 lg:px-10">
<AppHeader
:search-query="searchQuery"
:active-category="activeCategory"
@@ -400,16 +395,16 @@ const openDetail = async (app: App | Record<string, unknown>) => {
if (fullApp.isMerged && (fullApp.sparkApp || fullApp.apmApp)) {
const [sparkInstalled, apmInstalled] = await Promise.all([
fullApp.sparkApp
? (window.ipcRenderer.invoke("check-installed", {
? window.ipcRenderer.invoke("check-installed", {
pkgname: fullApp.sparkApp.pkgname,
origin: "spark",
}) as Promise<boolean>)
}) as Promise<boolean>
: Promise.resolve(false),
fullApp.apmApp
? (window.ipcRenderer.invoke("check-installed", {
? window.ipcRenderer.invoke("check-installed", {
pkgname: fullApp.apmApp.pkgname,
origin: "apm",
}) as Promise<boolean>)
}) as Promise<boolean>
: Promise.resolve(false),
]);
if (sparkInstalled && !apmInstalled) {
@@ -422,9 +417,9 @@ const openDetail = async (app: App | Record<string, unknown>) => {
const displayAppForScreenshots =
fullApp.viewingOrigin !== undefined && fullApp.isMerged
? ((fullApp.viewingOrigin === "spark"
? (fullApp.viewingOrigin === "spark"
? fullApp.sparkApp
: fullApp.apmApp) ?? fullApp)
: fullApp.apmApp) ?? fullApp
: fullApp;
currentApp.value = fullApp;

View File

@@ -1,25 +1,22 @@
@import "tailwindcss";
@theme {
--font-sans: "Plus Jakarta Sans", "Inter", "system-ui", "-apple-system", "Segoe UI", "sans-serif";
--font-sans: "Inter", "system-ui", "-apple-system", "Segoe UI", "sans-serif";
--color-brand: #2563eb;
--color-brand-dark: #1d4ed8;
--color-brand-soft: #60a5fa;
--color-surface-light: #f1f5f9;
--color-surface-dark: #0f172a;
--color-surface-light: #f5f7fb;
--color-surface-dark: #0b1220;
--color-card-light: #ffffff;
--color-card-dark: #1e293b;
--color-card-dark: #151c2c;
--shadow-glass: 0 4px 24px rgba(15, 23, 42, 0.06);
--shadow-glassDark: 0 24px 48px rgba(0, 0, 0, 0.4);
--shadow-card: 0 1px 3px rgba(0, 0, 0, 0.05);
--shadow-card-hover: 0 12px 40px rgba(15, 23, 42, 0.12);
--shadow-glass: 0 10px 30px rgba(15,23,42,0.08);
--shadow-glassDark: 0 20px 45px rgba(0,0,0,0.45);
--radius-xl: 1rem;
--radius-2xl: 1.25rem;
}
@variant dark (&:where(.dark, .dark *));
@@ -30,12 +27,11 @@
background-color: var(--color-surface-light);
color: #0f172a;
min-height: 100vh;
-webkit-font-smoothing: antialiased;
}
:root.dark body {
background-color: var(--color-surface-dark);
color: #f1f5f9;
color: #f8fafc;
}
#app {
@@ -44,13 +40,6 @@
}
@layer utilities {
.line-clamp-2 {
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.scrollbar-muted {
scrollbar-width: thin;
scrollbar-color: #94a3b8 transparent;

View File

@@ -1,40 +1,36 @@
<template>
<article
role="button"
tabindex="0"
<div
@click="openDetail"
@keydown.enter="openDetail"
@keydown.space.prevent="openDetail"
class="group flex h-full cursor-pointer gap-4 rounded-2xl border border-slate-200/60 bg-white/95 p-4 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:border-brand/30 hover:shadow-md hover:shadow-slate-200/50 dark:border-slate-700/50 dark:bg-slate-800/70 dark:hover:border-brand/40 dark:hover:shadow-slate-900/50"
class="group flex h-full cursor-pointer gap-4 rounded-2xl border border-slate-200/70 bg-white/90 p-4 shadow-sm transition hover:-translate-y-1 hover:border-brand/50 hover:shadow-lg dark:border-slate-800/60 dark:bg-slate-900/60"
>
<div
class="flex h-14 w-14 shrink-0 items-center justify-center overflow-hidden rounded-xl bg-gradient-to-br from-slate-100 to-slate-200/80 shadow-inner ring-1 ring-slate-200/50 dark:from-slate-700 dark:to-slate-800 dark:ring-slate-600/30"
class="flex h-16 w-16 items-center justify-center overflow-hidden rounded-2xl bg-gradient-to-b from-slate-100 to-slate-200 shadow-inner dark:from-slate-800 dark:to-slate-700"
>
<img
ref="iconImg"
:src="loadedIcon"
alt=""
alt="icon"
:class="[
'h-full w-full object-cover transition-opacity duration-300',
isLoaded ? 'opacity-100' : 'opacity-0',
]"
/>
</div>
<div class="flex min-w-0 flex-1 flex-col gap-1.5">
<div class="flex flex-wrap items-center gap-2">
<h3
<div class="flex flex-1 flex-col gap-1 overflow-hidden">
<div class="flex items-center gap-2">
<div
class="truncate text-base font-semibold text-slate-900 dark:text-white"
>
{{ app.name || "" }}
</h3>
</div>
<span
:class="[
'shrink-0 rounded-md px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wider',
'rounded-md px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wider shadow-sm',
app.isMerged
? 'bg-violet-100 text-violet-600 dark:bg-violet-900/40 dark:text-violet-300'
? 'bg-purple-100 text-purple-600 dark:bg-purple-900/30 dark:text-purple-400'
: app.origin === 'spark'
? 'bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300'
: 'bg-sky-100 text-sky-600 dark:bg-sky-900/40 dark:text-sky-300',
? 'bg-orange-100 text-orange-600 dark:bg-orange-900/30 dark:text-orange-400'
: 'bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400',
]"
>
{{
@@ -46,18 +42,14 @@
}}
</span>
</div>
<p
class="truncate text-xs font-medium text-slate-500 dark:text-slate-400"
>
<div class="text-sm text-slate-500 dark:text-slate-400">
{{ app.pkgname || "" }} · {{ app.version || "" }}
</p>
<p
class="line-clamp-2 text-sm leading-snug text-slate-500 dark:text-slate-400"
>
</div>
<div class="text-sm text-slate-500 dark:text-slate-400">
{{ description }}
</p>
</div>
</div>
</article>
</div>
</template>
<script setup lang="ts">

View File

@@ -10,16 +10,16 @@
<div
v-if="show"
v-bind="attrs"
class="fixed inset-0 z-50 flex items-center justify-center overflow-hidden bg-slate-900/60 backdrop-blur-sm p-4"
class="fixed inset-0 z-50 flex items-center justify-center overflow-hidden bg-slate-900/70 p-4"
@click.self="closeModal"
>
<div
class="modal-panel relative w-full max-w-4xl max-h-[85vh] overflow-y-auto scrollbar-nowidth rounded-2xl border border-slate-200/60 bg-white/98 p-6 shadow-2xl dark:border-slate-700/50 dark:bg-slate-900/98"
class="modal-panel relative w-full max-w-4xl max-h-[85vh] overflow-y-auto scrollbar-nowidth rounded-3xl border border-white/10 bg-white/95 p-6 shadow-2xl dark:border-slate-800 dark:bg-slate-900"
>
<div class="flex flex-col gap-4 lg:flex-row lg:items-center">
<div class="flex flex-1 items-center gap-4">
<div
class="flex h-20 w-20 shrink-0 items-center justify-center overflow-hidden rounded-2xl bg-gradient-to-br from-slate-100 to-slate-200/80 shadow-inner ring-1 ring-slate-200/50 dark:from-slate-700 dark:to-slate-800 dark:ring-slate-600/30"
class="flex h-20 w-20 items-center justify-center overflow-hidden rounded-3xl bg-gradient-to-b from-slate-100 to-slate-200 shadow-inner dark:from-slate-800 dark:to-slate-700"
>
<img
v-if="app"
@@ -133,11 +133,11 @@
</template>
<button
type="button"
class="inline-flex h-10 w-10 items-center justify-center rounded-xl border border-slate-200/60 text-slate-500 transition hover:bg-slate-100 hover:text-slate-700 dark:border-slate-700 dark:hover:bg-slate-800 dark:hover:text-slate-200"
class="inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200/70 text-slate-500 transition hover:text-slate-900 dark:border-slate-700"
@click="closeModal"
aria-label="关闭"
>
<i class="fas fa-xmark text-sm"></i>
<i class="fas fa-xmark"></i>
</button>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<template>
<div
v-if="!loading"
class="mt-6 grid gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4"
class="mt-6 grid gap-5 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4"
>
<AppCard
v-for="(app, index) in apps"

View File

@@ -1,13 +1,12 @@
<template>
<header class="flex flex-col gap-4">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:gap-5">
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center">
<div class="flex items-center gap-3">
<button
type="button"
class="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-slate-200/60 bg-white/90 text-slate-500 shadow-sm backdrop-blur-sm transition hover:border-slate-300 hover:bg-white hover:text-slate-700 lg:hidden dark:border-slate-700/60 dark:bg-slate-800/80 dark:text-slate-400 dark:hover:bg-slate-700 dark:hover:text-slate-200"
class="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl border border-slate-200/70 bg-white/80 text-slate-500 shadow-sm backdrop-blur transition hover:bg-slate-50 lg:hidden dark:border-slate-800/70 dark:bg-slate-900/60 dark:text-slate-400 dark:hover:bg-slate-800"
@click="$emit('toggle-sidebar')"
title="切换侧边栏"
aria-label="切换侧边栏"
>
<i class="fas fa-bars"></i>
</button>
@@ -17,19 +16,16 @@
@open-install-settings="$emit('open-install-settings')"
/>
</div>
<div class="w-full flex-1 min-w-0">
<div class="w-full flex-1">
<label for="searchBox" class="sr-only">搜索应用</label>
<div class="relative">
<span
class="pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 flex h-8 w-8 items-center justify-center rounded-lg bg-slate-100/80 text-slate-400 dark:bg-slate-800/80 dark:text-slate-500"
aria-hidden="true"
>
<i class="fas fa-search text-sm"></i>
</span>
<i
class="fas fa-search pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-slate-400"
></i>
<input
id="searchBox"
v-model="localSearchQuery"
class="w-full rounded-xl border border-slate-200/70 bg-white/95 py-3 pl-12 pr-4 text-sm text-slate-800 shadow-sm outline-none transition placeholder:text-slate-400 focus:border-brand/60 focus:ring-2 focus:ring-brand/20 dark:border-slate-700/70 dark:bg-slate-800/80 dark:text-slate-100 dark:placeholder:text-slate-500 dark:focus:border-brand/50 dark:focus:ring-brand/20"
class="w-full rounded-2xl border border-slate-200/70 bg-white/80 py-3 pl-12 pr-4 text-sm text-slate-700 shadow-sm outline-none transition placeholder:text-slate-400 focus:border-brand/50 focus:ring-4 focus:ring-brand/10 dark:border-slate-800/70 dark:bg-slate-900/60 dark:text-slate-200"
placeholder="搜索应用名 / 包名 / 标签,按回车键搜索"
@keydown.enter="handleSearch"
@focus="handleSearchFocus"
@@ -39,16 +35,12 @@
</div>
<div
v-if="activeCategory !== 'home'"
class="text-sm text-slate-500 dark:text-slate-400"
id="currentCount"
class="text-sm font-medium text-slate-500 dark:text-slate-400"
>
<span class="tabular-nums text-slate-700 dark:text-slate-300">{{
appsCount
}}</span>
个应用
{{ appsCount }} 个应用
</div>
</header>
</div>
</template>
<script setup lang="ts">

View File

@@ -1,87 +1,62 @@
<template>
<div class="flex h-full flex-col gap-5">
<div class="flex h-full flex-col gap-6">
<div class="flex items-center justify-between gap-3">
<div class="flex items-center gap-3">
<div
class="flex h-12 w-12 items-center justify-center overflow-hidden rounded-2xl bg-gradient-to-br from-brand/20 to-brand/5 ring-1 ring-slate-200/60 dark:ring-slate-700/50"
>
<img :src="amberLogo" alt="Amber PM" class="h-8 w-8 object-contain" />
</div>
<div class="flex flex-col min-w-0">
<img
:src="amberLogo"
alt="Amber PM"
class="h-11 w-11 rounded-2xl bg-white/70 p-2 shadow-sm ring-1 ring-slate-900/5 dark:bg-slate-800"
/>
<div class="flex flex-col">
<span
class="text-[10px] font-medium uppercase tracking-widest text-slate-400 dark:text-slate-500"
class="text-xs uppercase tracking-[0.3em] text-slate-500 dark:text-slate-400"
>Spark Store</span
>
<span
class="truncate text-base font-bold tracking-tight text-slate-800 dark:text-white"
<span class="text-lg font-semibold text-slate-900 dark:text-white"
>星火应用商店</span
>
</div>
</div>
<button
type="button"
class="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-slate-400 transition hover:bg-slate-100 hover:text-slate-600 lg:hidden dark:hover:bg-slate-800 dark:hover:text-slate-300"
class="inline-flex h-10 w-10 items-center justify-center rounded-2xl text-slate-400 hover:bg-slate-100 lg:hidden dark:hover:bg-slate-800"
@click="$emit('close')"
title="关闭侧边栏"
aria-label="关闭侧边栏"
>
<i class="fas fa-times text-sm"></i>
<i class="fas fa-times"></i>
</button>
</div>
<ThemeToggle :theme-mode="themeMode" @toggle="toggleTheme" />
<StoreModeSwitcher />
<nav
class="flex-1 space-y-1 overflow-y-auto scrollbar-muted pr-1"
aria-label="分类导航"
>
<div class="flex-1 space-y-2 overflow-y-auto scrollbar-muted pr-2">
<button
type="button"
class="nav-item flex w-full items-center gap-3 rounded-xl border border-transparent px-3.5 py-2.5 text-left text-sm font-medium transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40"
class="flex w-full items-center gap-3 rounded-2xl border border-transparent px-4 py-3 text-left text-sm font-medium text-slate-600 transition hover:border-brand/30 hover:bg-brand/5 hover:text-brand focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40 dark:text-slate-300 dark:hover:bg-slate-800"
:class="
activeCategory === 'home'
? 'nav-item-active border-brand/20 bg-brand/10 text-brand dark:bg-brand/20 dark:text-brand-soft'
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-800 dark:text-slate-400 dark:hover:bg-slate-800/80 dark:hover:text-slate-200'
? 'border-brand/40 bg-brand/10 text-brand dark:bg-brand/15'
: ''
"
@click="selectCategory('home')"
>
<span
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg transition-colors"
:class="
activeCategory === 'home'
? 'bg-brand/15 text-brand dark:bg-brand/25 dark:text-brand-soft'
: 'bg-slate-100/80 text-slate-500 dark:bg-slate-800/80 dark:text-slate-400'
"
>
<i class="fas fa-home"></i>
</span>
<span class="flex-1 truncate">主页</span>
<span>主页</span>
</button>
<button
type="button"
class="nav-item flex w-full items-center gap-3 rounded-xl border border-transparent px-3.5 py-2.5 text-left text-sm font-medium transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40"
class="flex w-full items-center gap-3 rounded-2xl border border-transparent px-4 py-3 text-left text-sm font-medium text-slate-600 transition hover:border-brand/30 hover:bg-brand/5 hover:text-brand focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40 dark:text-slate-300 dark:hover:bg-slate-800"
:class="
activeCategory === 'all'
? 'nav-item-active border-brand/20 bg-brand/10 text-brand dark:bg-brand/20 dark:text-brand-soft'
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-800 dark:text-slate-400 dark:hover:bg-slate-800/80 dark:hover:text-slate-200'
? 'border-brand/40 bg-brand/10 text-brand dark:bg-brand/15'
: ''
"
@click="selectCategory('all')"
>
<span>全部应用</span>
<span
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg transition-colors"
:class="
activeCategory === 'all'
? 'bg-brand/15 text-brand dark:bg-brand/25 dark:text-brand-soft'
: 'bg-slate-100/80 text-slate-500 dark:bg-slate-800/80 dark:text-slate-400'
"
>
<i class="fas fa-th-large"></i>
</span>
<span class="flex-1 truncate">全部应用</span>
<span
class="rounded-full bg-slate-200/80 px-2.5 py-0.5 text-xs font-semibold tabular-nums text-slate-600 dark:bg-slate-700/80 dark:text-slate-300"
class="ml-auto rounded-full bg-slate-100 px-2 py-0.5 text-xs font-semibold text-slate-500 dark:bg-slate-800/70 dark:text-slate-300"
>{{ categoryCounts.all || 0 }}</span
>
</button>
@@ -90,31 +65,25 @@
v-for="(category, key) in categories"
:key="key"
type="button"
class="nav-item flex w-full items-center gap-3 rounded-xl border border-transparent px-3.5 py-2.5 text-left text-sm font-medium transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40"
class="flex w-full items-center gap-3 rounded-2xl border border-transparent px-4 py-3 text-left text-sm font-medium text-slate-600 transition hover:border-brand/30 hover:bg-brand/5 hover:text-brand focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40 dark:text-slate-300 dark:hover:bg-slate-800"
:class="
activeCategory === key
? 'nav-item-active border-brand/20 bg-brand/10 text-brand dark:bg-brand/20 dark:text-brand-soft'
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-800 dark:text-slate-400 dark:hover:bg-slate-800/80 dark:hover:text-slate-200'
? 'border-brand/40 bg-brand/10 text-brand dark:bg-brand/15'
: ''
"
@click="selectCategory(key)"
>
<span
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg transition-colors"
:class="
activeCategory === key
? 'bg-brand/15 text-brand dark:bg-brand/25 dark:text-brand-soft'
: 'bg-slate-100/80 text-slate-500 dark:bg-slate-800/80 dark:text-slate-400'
"
>
<i class="fas fa-folder"></i>
<span class="flex flex-col">
<span>
<div class="text-left">{{ category.zh }}</div>
</span>
</span>
<span class="flex-1 truncate text-left">{{ category.zh }}</span>
<span
class="rounded-full bg-slate-200/80 px-2.5 py-0.5 text-xs font-semibold tabular-nums text-slate-600 dark:bg-slate-700/80 dark:text-slate-300"
class="ml-auto rounded-full bg-slate-100 px-2 py-0.5 text-xs font-semibold text-slate-500 dark:bg-slate-800/70 dark:text-slate-300"
>{{ categoryCounts[key] || 0 }}</span
>
</button>
</nav>
</div>
</div>
</template>

View File

@@ -1,45 +1,40 @@
<template>
<div
class="fixed inset-x-4 bottom-4 z-40 rounded-2xl border border-slate-200/60 bg-white/95 shadow-xl shadow-slate-200/30 backdrop-blur-xl dark:border-slate-700/50 dark:bg-slate-900/95 dark:shadow-none sm:left-auto sm:right-6 sm:w-[22rem]"
class="fixed inset-x-4 bottom-4 z-40 rounded-3xl border border-slate-200/70 bg-white/95 shadow-2xl backdrop-blur dark:border-slate-800/70 dark:bg-slate-900/90 sm:left-auto sm:right-6 sm:w-96"
>
<div
class="flex cursor-pointer items-center justify-between px-4 py-3.5 transition hover:bg-slate-50/80 dark:hover:bg-slate-800/50"
class="flex items-center justify-between px-5 py-4"
@click="toggleExpand"
>
<div class="flex items-center gap-2.5">
<span
class="flex h-9 w-9 items-center justify-center rounded-xl bg-brand/10 text-brand dark:bg-brand/20"
>
<i class="fas fa-download text-sm"></i>
</span>
<span class="text-sm font-semibold text-slate-800 dark:text-slate-100"
>下载队列</span
>
<div
class="flex items-center gap-2 text-sm font-semibold text-slate-700 dark:text-slate-200"
>
<i class="fas fa-download text-brand"></i>
<span>下载队列</span>
<span
v-if="downloads.length"
class="rounded-full bg-slate-200/80 px-2 py-0.5 text-xs font-semibold tabular-nums text-slate-600 dark:bg-slate-700/80 dark:text-slate-300"
class="rounded-full bg-slate-100 px-2 py-0.5 text-xs font-medium text-slate-500 dark:bg-slate-800/70 dark:text-slate-300"
>
{{ activeDownloads }}/{{ downloads.length }}
({{ activeDownloads }}/{{ downloads.length }})
</span>
</div>
<div class="flex items-center gap-1">
<div class="flex items-center gap-2">
<button
v-if="downloads.length"
type="button"
class="inline-flex h-8 w-8 items-center justify-center rounded-lg text-slate-500 transition hover:bg-slate-100 hover:text-slate-700 dark:hover:bg-slate-700 dark:hover:text-slate-300"
class="inline-flex h-9 w-9 items-center justify-center rounded-full border border-slate-200/70 text-slate-500 transition hover:text-slate-900 dark:border-slate-700 dark:text-slate-400"
title="清除已完成"
@click.stop="clearCompleted"
>
<i class="fas fa-broom text-sm"></i>
<i class="fas fa-broom"></i>
</button>
<button
type="button"
class="inline-flex h-8 w-8 items-center justify-center rounded-lg text-slate-500 transition hover:bg-slate-100 hover:text-slate-700 dark:hover:bg-slate-700 dark:hover:text-slate-300"
class="inline-flex h-9 w-9 items-center justify-center rounded-full border border-slate-200/70 text-slate-500 transition hover:text-slate-900 dark:border-slate-700 dark:text-slate-400"
@click.stop="toggleExpand"
:aria-expanded="isExpanded"
>
<i
class="fas text-sm transition-transform"
class="fas"
:class="isExpanded ? 'fa-chevron-down' : 'fa-chevron-up'"
></i>
</button>
@@ -54,22 +49,19 @@
leave-from-class="opacity-100 translate-y-0"
leave-to-class="opacity-0 -translate-y-2"
>
<div
v-show="isExpanded"
class="max-h-80 overflow-y-auto border-t border-slate-200/60 px-3 py-3 scrollbar-muted dark:border-slate-700/50"
>
<div v-show="isExpanded" class="max-h-96 overflow-y-auto px-3 pb-4">
<div
v-if="downloads.length === 0"
class="flex flex-col items-center justify-center rounded-xl border border-dashed border-slate-200/80 py-10 text-slate-500 dark:border-slate-700/80 dark:text-slate-400"
class="flex flex-col items-center justify-center rounded-2xl border border-dashed border-slate-200/80 px-4 py-12 text-slate-500 dark:border-slate-800/80 dark:text-slate-400"
>
<i class="fas fa-inbox text-2xl opacity-60"></i>
<p class="mt-2 text-sm font-medium">暂无下载任务</p>
<i class="fas fa-inbox text-3xl"></i>
<p class="mt-3 text-sm">暂无下载任务</p>
</div>
<div v-else class="space-y-2">
<div
v-for="download in downloads"
:key="download.id"
class="flex cursor-pointer items-center gap-3 rounded-xl border border-slate-200/60 bg-white/95 p-3 transition hover:border-brand/30 hover:bg-slate-50/80 dark:border-slate-700/50 dark:bg-slate-800/80 dark:hover:border-brand/40 dark:hover:bg-slate-800/90"
class="flex cursor-pointer items-center gap-3 rounded-2xl border border-slate-200/70 bg-white/90 p-3 shadow-sm transition hover:border-brand/40 hover:shadow-lg dark:border-slate-800/70 dark:bg-slate-900"
:class="
download.status === 'failed'
? 'border-rose-300/70 dark:border-rose-500/40'
@@ -78,7 +70,7 @@
@click="showDownloadDetail(download)"
>
<div
class="h-11 w-11 shrink-0 overflow-hidden rounded-xl bg-slate-100 dark:bg-slate-700/80 ring-1 ring-slate-200/50 dark:ring-slate-600/50"
class="h-12 w-12 overflow-hidden rounded-xl bg-slate-100 dark:bg-slate-800"
>
<img
:src="download.icon"

View File

@@ -1,5 +1,5 @@
<template>
<div class="space-y-8">
<div class="space-y-8">
<div
v-if="loading"
class="flex flex-col items-center justify-center py-12 text-slate-500 dark:text-slate-400"
@@ -13,6 +13,7 @@
>
{{ error }}
</div>
<div v-else-if="error" class="text-center text-rose-600">{{ error }}</div>
<div v-else>
<div class="grid gap-4 auto-fit-grid">
<a
@@ -20,40 +21,29 @@
:key="link.url + link.name"
:href="link.type === '_blank' ? undefined : link.url"
@click.prevent="onLinkClick(link)"
class="flex flex-col items-start gap-3 rounded-2xl border border-slate-200/60 bg-white/95 p-4 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:border-brand/30 hover:shadow-md dark:border-slate-700/50 dark:bg-slate-800/70 dark:hover:border-brand/40"
class="flex flex-col items-start gap-2 rounded-2xl border border-slate-200/70 bg-white/90 p-4 shadow-sm hover:shadow-lg transition"
:title="link.more as string"
>
<div
class="flex h-16 w-full items-center justify-center overflow-hidden rounded-xl bg-slate-50 dark:bg-slate-800/80"
>
<img
:src="computedImgUrl(link)"
class="max-h-14 w-auto object-contain"
loading="lazy"
alt=""
/>
</div>
<div class="text-base font-semibold text-slate-900 dark:text-white">
<img
:src="computedImgUrl(link)"
class="h-20 w-full object-contain"
loading="lazy"
/>
<div class="text-base font-semibold text-slate-900">
{{ link.name }}
</div>
<div class="text-sm text-slate-500 dark:text-slate-400 line-clamp-2">
{{ link.more }}
</div>
<div class="text-sm text-slate-500">{{ link.more }}</div>
</a>
</div>
<div class="space-y-6 mt-8">
<section
v-for="section in lists"
:key="section.title"
class="space-y-4"
>
<h3
class="text-lg font-bold tracking-tight text-slate-800 dark:text-slate-100 border-b border-slate-200/70 dark:border-slate-700/70 pb-2"
>
{{ section.title }}
</h3>
<div class="grid gap-4 auto-fit-grid">
<div class="space-y-6 mt-6">
<section v-for="section in lists" :key="section.title">
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold text-slate-900">
{{ section.title }}
</h3>
</div>
<div class="mt-3 grid gap-4 auto-fit-grid">
<AppCard
v-for="app in section.apps"
:key="app.pkgname"

View File

@@ -1,27 +1,23 @@
<template>
<button
type="button"
class="flex w-full items-center justify-between rounded-xl border border-slate-200/60 bg-white/80 px-3.5 py-2.5 text-sm font-medium text-slate-600 shadow-sm transition hover:border-slate-300 hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40 dark:border-slate-700/60 dark:bg-slate-800/80 dark:text-slate-300 dark:hover:border-slate-600 dark:hover:bg-slate-800"
class="flex items-center justify-between rounded-2xl border border-slate-200/80 bg-white/70 px-4 py-3 text-sm font-medium text-slate-600 shadow-sm transition hover:border-brand/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40 dark:border-slate-800/70 dark:bg-slate-900/60 dark:text-slate-300"
:aria-pressed="themeMode === 'dark'"
@click="toggle"
>
<span class="flex items-center gap-2.5">
<span
class="flex h-7 w-7 items-center justify-center rounded-lg bg-slate-100/80 dark:bg-slate-700/80"
>
<i class="fas text-sm" :class="iconClass"></i>
</span>
<span class="flex items-center gap-2">
<i class="fas" :class="iconClass"></i>
<span>{{ label }}</span>
</span>
<span
class="relative inline-flex h-6 w-11 shrink-0 items-center rounded-full bg-slate-200/90 transition dark:bg-slate-600/80"
class="relative inline-flex h-6 w-12 items-center rounded-full bg-slate-300/80 transition dark:bg-slate-700"
>
<span
:class="[
'absolute top-1/2 h-5 w-5 -translate-y-1/2 rounded-full bg-white shadow-md ring-2 ring-slate-200/50 transition-all duration-200 dark:ring-slate-600/50',
'inline-block h-4 w-4 rounded-full bg-white shadow transition',
togglePosition,
]"
/>
></span>
</span>
</button>
</template>
@@ -54,8 +50,8 @@ const iconClass = computed(() => {
});
const togglePosition = computed(() => {
if (props.themeMode === "auto") return "left-1/2 -translate-x-1/2";
if (props.themeMode === "dark") return "left-6";
return "left-0.5";
if (props.themeMode === "auto") return "translate-x-4";
if (props.themeMode === "dark") return "translate-x-7";
return "translate-x-1";
});
</script>

View File

@@ -1,21 +1,21 @@
<template>
<div class="flex flex-wrap gap-2">
<div class="flex flex-wrap gap-3">
<button
type="button"
class="inline-flex items-center gap-2 rounded-xl bg-gradient-to-r from-brand to-brand-dark px-3.5 py-2 text-sm font-semibold text-white shadow-md transition hover:shadow-lg hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-slate-900"
class="inline-flex items-center gap-2 rounded-2xl bg-gradient-to-r from-brand to-brand-dark px-4 py-2 text-sm font-semibold text-white shadow-lg transition hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40"
@click="handleUpdate"
title="检查可更新的软件包列表"
>
<i class="fas fa-sync-alt text-xs"></i>
<i class="fas fa-sync-alt"></i>
<span>软件更新</span>
</button>
<button
type="button"
class="inline-flex items-center gap-2 rounded-xl border border-slate-200/70 bg-white/90 px-3.5 py-2 text-sm font-semibold text-slate-700 shadow-sm transition hover:border-slate-300 hover:bg-slate-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40 dark:border-slate-700 dark:bg-slate-800/80 dark:text-slate-200 dark:hover:bg-slate-700/80"
class="inline-flex items-center gap-2 rounded-2xl bg-gradient-to-r from-brand to-brand-dark px-4 py-2 text-sm font-semibold text-white shadow-lg transition hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/40"
@click="handleSettings"
title="安装设置"
>
<i class="fas fa-cog text-xs"></i>
<i class="fas fa-cog"></i>
<span>安装设置</span>
</button>
<!-- <button