From 37567f4ef8a2dfa26fed86d4133420123b010c81 Mon Sep 17 00:00:00 2001 From: grtsinry43 Date: Fri, 25 Apr 2025 17:00:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9D=E6=AD=A5=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/BrowseMirrors.svelte | 337 +++++++++++++++++++++++++ src/components/Header.svelte | 135 ++++++---- src/components/MirrorList.svelte | 33 ++- src/components/MirrorUsageGuide.svelte | 334 ++++++++++++++++++++++++ src/components/PopularMirrors.svelte | 296 ++++++++++++++++++++++ src/components/Welcome.astro | 210 --------------- src/layouts/BasicLayout.astro | 73 ++++-- src/pages/about.astro | 187 ++++++++++++++ src/pages/browse.astro | 70 +++++ src/pages/index.astro | 62 ++++- src/pages/mirror/[slug].astro | 68 +++++ src/pages/mirrors.astro | 56 ++++ src/pages/new.astro | 55 ++++ src/pages/popular.astro | 57 +++++ 14 files changed, 1678 insertions(+), 295 deletions(-) create mode 100644 src/components/BrowseMirrors.svelte create mode 100644 src/components/MirrorUsageGuide.svelte create mode 100644 src/components/PopularMirrors.svelte delete mode 100644 src/components/Welcome.astro create mode 100644 src/pages/about.astro create mode 100644 src/pages/browse.astro create mode 100644 src/pages/mirror/[slug].astro create mode 100644 src/pages/mirrors.astro create mode 100644 src/pages/new.astro create mode 100644 src/pages/popular.astro diff --git a/src/components/BrowseMirrors.svelte b/src/components/BrowseMirrors.svelte new file mode 100644 index 0000000..de5d10c --- /dev/null +++ b/src/components/BrowseMirrors.svelte @@ -0,0 +1,337 @@ + + +
+
+ +
+
+ +
+
+ + + +
+ +
+ + +
+
+ + + +
+ +
+ + +
+
+ +
+ +
+
+ + +
+
+ + +
+ +
+ 共 {filteredMirrors.length} 个镜像 + +
+
+
+ + + {#if loading} +
+
+
+ + {:else if error} +
+

加载失败: {error}

+ +
+ + {:else if viewMode === 'grid'} + {#if filteredMirrors.length > 0} + + {:else} +
+
🔍
+

未找到符合条件的镜像

+ +
+ {/if} + + {:else} + {#if filteredMirrors.length > 0} +
+ + + + + + + + + + + + {#each filteredMirrors as mirror} + window.location.href = `/mirrors/${mirror.name}`} + > + + + + + + + {/each} + +
镜像名称类别状态大小最后更新时间
+ {getMirrorIcon(mirror.name)} + {mirror.name} + {mirror.category} + + {formatStatus(mirror.status)} + + {mirror.size || 'N/A'}{mirror.lastUpdated}
+
+ {:else} +
+
🔍
+

未找到符合条件的镜像

+ +
+ {/if} + {/if} +
+
+ + + + diff --git a/src/components/Header.svelte b/src/components/Header.svelte index db5c406..6adf7a6 100644 --- a/src/components/Header.svelte +++ b/src/components/Header.svelte @@ -1,6 +1,7 @@
+ class="sticky top-0 z-50 w-full transition-all duration-300 {isScrolled ? 'shadow-lg' : 'shadow-md'} + {isScrolled ? 'bg-surface-100-800-token/95' : 'bg-surface-100-800-token/80'} + backdrop-blur-2xl border-b border-surface-300-600-token">
@@ -91,10 +120,10 @@ bind:value={searchQuery} on:keydown={handleSearch} placeholder="搜索镜像..." - class="input input-sm pl-9 pr-4 rounded-full w-40 lg:w-64 focus:w-72 transition-all duration-300" + class="input input-sm pl-9 pr-4 rounded-full w-40 lg:w-64 focus:w-72 transition-all duration-300 focus:ring-primary-500" />
\ No newline at end of file diff --git a/src/components/MirrorList.svelte b/src/components/MirrorList.svelte index 82a2a4c..440c65e 100644 --- a/src/components/MirrorList.svelte +++ b/src/components/MirrorList.svelte @@ -2,10 +2,14 @@ import { onMount } from "svelte"; import { Toaster, createToaster } from "@skeletonlabs/skeleton-svelte"; + // 接收服务端渲染的初始数据 + export let initialMirrors = []; + export let initialError = null; + // 状态变量 - let mirrors = []; - let loading = true; - let error = null; + let mirrors = initialMirrors; + let loading = initialMirrors.length === 0 && !initialError; + let error = initialError; let searchTerm = ""; let sortBy = "name"; // 默认按名称排序 @@ -31,7 +35,7 @@ // 格式化最后更新时间 lastUpdated: new Date(info.last_update_ts * 1000).toLocaleString("zh-CN") })); - + error = null; } catch (err) { error = err.message; console.error(err); @@ -72,9 +76,17 @@ } } + // 跳转到镜像详情页 + function goToMirrorPage(mirrorName) { + window.location.href = `/mirror/${mirrorName}`; + } + onMount(() => { - fetchMirrors(); - console.log("Mounted and fetching mirrors..."); + // 如果没有初始数据或有错误时,才在客户端请求数据 + if (initialMirrors.length === 0 && !initialError) { + fetchMirrors(); + } + console.log("Component mounted with initial data:", initialMirrors.length); }); @@ -134,12 +146,13 @@ {#each filteredMirrors as mirror (mirror.name)} + mirror.status === 'syncing' ? 'bg-yellow-500/10' : ''} hover:bg-surface-200/50 transition-colors duration-300 cursor-pointer" + on:click={() => goToMirrorPage(mirror.name)}> {mirror.name} - - {mirror.status === 'success' ? '正常' : mirror.status === 'failed' ? '失败' : mirror.status === 'syncing' ? '同步中' : mirror.status} - + + {mirror.status === 'success' ? '正常' : mirror.status === 'failed' ? '失败' : mirror.status === 'syncing' ? '同步中' : mirror.status} + {mirror.size || 'N/A'} {mirror.lastUpdated} diff --git a/src/components/MirrorUsageGuide.svelte b/src/components/MirrorUsageGuide.svelte new file mode 100644 index 0000000..88f1a44 --- /dev/null +++ b/src/components/MirrorUsageGuide.svelte @@ -0,0 +1,334 @@ + + +
+
+

{mirror.name} {mirror.status === 'success' ? '正常' : mirror.status === 'failed' ? '失败' : '同步中'} +

+

{tutorial.description}

+ +
+
+
+ + + + +
+
+

状态

+

{mirror.status === 'success' ? '正常运行中' : mirror.status === 'failed' ? '同步失败' : '正在同步'}

+
+
+ +
+
+ + + +
+
+

最后更新

+

{lastUpdateFormatted}

+
+
+ +
+
+ + + +
+
+

镜像大小

+

{mirror.size || '暂无数据'}

+
+
+
+
+ + + {#each processedTabs as tab, i} + {tab.label} + {/each} + + {#each processedTabs as tab, i} + + {@html tab.content} + + {/each} + +
+ + diff --git a/src/components/PopularMirrors.svelte b/src/components/PopularMirrors.svelte new file mode 100644 index 0000000..81acb37 --- /dev/null +++ b/src/components/PopularMirrors.svelte @@ -0,0 +1,296 @@ + + +
+
+
+
+ + + +
+ + +
+ + + {#if loading} +
+
+
+ + {:else if error} +
+

加载失败: {error}

+ +
+ + {:else} +
+ + + + +
+

更多热门镜像

+ +
+ + + + + + + + + + + + + {#each mirrors.slice(3, 20) as mirror, i} + window.location.href = `/mirror/${mirror.name}`}> + + + + + + + + {/each} + +
排名镜像名称状态下载量趋势最后更新
{i + 4}{mirror.name} + + {mirror.status === 'success' ? '正常' : mirror.status === 'failed' ? '失败' : mirror.status === 'syncing' ? '同步中' : mirror.status} + + + {timeRange === 'week' ? formatNumber(mirror.weeklyDownloads) : + timeRange === 'month' ? formatNumber(mirror.monthlyDownloads) : + formatNumber(mirror.yearlyDownloads)} + + {#if mirror.trend !== undefined} + {@const trendInfo = getTrendInfo(mirror.trend)} +
+ {#if trendInfo.icon} + + {/if} + {trendInfo.text} +
+ {/if} +
{mirror.lastUpdated}
+
+
+
+ {/if} +
+
+ + + + diff --git a/src/components/Welcome.astro b/src/components/Welcome.astro deleted file mode 100644 index 52e0333..0000000 --- a/src/components/Welcome.astro +++ /dev/null @@ -1,210 +0,0 @@ ---- -import astroLogo from '../assets/astro.svg'; -import background from '../assets/background.svg'; ---- - -
- -
-
- Astro Homepage -

- To get started, open the
src/pages
directory in your project. -

- -
-
- - - -

What's New in Astro 5.0?

-

- From content layers to server islands, click to learn more about the new features and - improvements in Astro 5.0 -

-
-
- - diff --git a/src/layouts/BasicLayout.astro b/src/layouts/BasicLayout.astro index dda9134..05664e9 100644 --- a/src/layouts/BasicLayout.astro +++ b/src/layouts/BasicLayout.astro @@ -1,30 +1,71 @@ --- -// src/layouts/BaseLayout.astro -import Header from "../components/Header.svelte"; // 引入 Svelte 头部组件 -import Footer from "../components/Footer.svelte"; // 引入 Svelte 页脚组件 -import "@/styles/global.css"; // 引入全局样式(包含 Tailwind 和 Skeleton 基础) +// src/layouts/BasicLayout.astro +import Header from "../components/Header.svelte"; +import Footer from "../components/Footer.svelte"; +import "@/styles/global.css"; -// 设置 HTML 的 data-theme 属性,让 Skeleton 主题生效 -// 注意:你可能需要 client:load 来确保 store 在客户端可用,或者在 中直接设置 -// 一个简单的示例,实际可能更复杂,取决于你的主题切换实现 -// const currentTheme = $theme; // 如果在 Astro 中直接读取 store +interface Props { + title?: string; + description?: string; + image?: string; + canonicalURL?: string; +} + +const { + title = "我的镜像站 | 高速文件下载服务", + description = "提供各类开源软件、系统镜像的高速下载服务", + image = "/images/social-preview.jpg", + canonicalURL = Astro.url.href, +} = Astro.props; --- - + - {Astro.props.title || "我的镜像站"} - + + + {title} + + + + + + + + + {image && } + + + + + + {image && } + + + + + + + - +
-
+