Refine frontend navigation, loading UI, and site copy
Some checks failed
docker-images / resolve-build-targets (push) Successful in 6s
ui-regression / playwright-regression (push) Failing after 13m3s
docker-images / build-and-push (admin) (push) Successful in 4s
docker-images / submit-indexnow (push) Has been cancelled
docker-images / build-and-push (frontend) (push) Has been cancelled
docker-images / build-and-push (backend) (push) Has been cancelled

This commit is contained in:
2026-04-03 23:43:30 +08:00
parent 99a57738e0
commit ad44dde886
14 changed files with 2121 additions and 825 deletions

View File

@@ -227,16 +227,6 @@ const discoverPrompt = hasActiveFilters
const postsPrompt = hasActiveFilters
? t('home.promptPostsFiltered', { count: previewCount, filters: activeFilterLabels.join(' · ') })
: t('home.promptPostsDefault', { count: previewCount });
const navLinks = [
{ icon: 'fa-file-code', text: t('nav.articles'), href: '/articles' },
{ icon: 'fa-folder', text: t('nav.categories'), href: '/categories' },
{ icon: 'fa-tags', text: t('nav.tags'), href: '/tags' },
{ icon: 'fa-stream', text: t('nav.timeline'), href: '/timeline' },
{ icon: 'fa-star', text: t('nav.reviews'), href: '/reviews' },
{ icon: 'fa-link', text: t('nav.friends'), href: '/friends' },
{ icon: 'fa-user-secret', text: t('nav.about'), href: '/about' },
...(siteSettings.ai.enabled ? [{ icon: 'fa-robot', text: t('nav.ask'), href: '/ask' }] : []),
];
const siteBaseUrl = (siteSettings.siteUrl || new URL(Astro.request.url).origin).replace(/\/$/, '');
const homeJsonLd = [
{
@@ -262,14 +252,18 @@ const homeShareCopy = isEnglish
'Use the homepage as the canonical top-level entry for people and AI search to branch into articles, taxonomies, reviews, and profile context.',
}
: {
badge: '页',
title: '分享首页',
description: '把首页发给别人,能快速看到文章、分类、评测和个人介绍等主要内容。',
badge: '入口页',
title: '把首页甩出去',
description: '不知道发什么时,先发这个入口。轻松、不剧透,还挺省心。',
};
const homeShareSummary = isEnglish
? 'A light entry point for curious visitors. Click around and let the rest reveal itself.'
: '这是一个适合顺手转发的小入口,先逛逛,细节留到点开再说。';
const homeSidebarCopy = isEnglish
? {
quickLinks: 'Quick links',
quickLinksDesc: 'Jump to the main sections of the site.',
quickLinksDesc: 'Keep the main channels pinned on the right so you can switch context without losing reading flow.',
quickLinksMore: 'More channels',
popularTitle: 'Hot now',
popularDesc: 'Track the most-read content in the selected window.',
friendsTitle: 'Friend links',
@@ -280,15 +274,28 @@ const homeSidebarCopy = isEnglish
}
: {
quickLinks: '快速入口',
quickLinksDesc: '常用入口收进侧栏,首页阅读流更清爽。',
quickLinksDesc: '常用入口都放这儿,手别忙,点就行。',
quickLinksMore: '更多频道',
popularTitle: '最近热门',
popularDesc: '按当前时间窗口查看最受关注的内容。',
popularDesc: '看看最近是谁在悄悄抢镜。',
friendsTitle: '友情链接',
friendsDesc: '先看几个常访问的站点入口。',
friendsDesc: '隔壁摊位也许也有好东西。',
statsTitle: '站点概览',
statsDesc: '快速看一下当前站点规模与内容状态。',
aiBriefTitle: '站点摘要',
statsDesc: '轻量围观一下站内气氛,不必知道太多。',
aiBriefTitle: '站点便签',
};
const primaryQuickLinks = [
{ icon: 'fa-file-code', text: t('nav.articles'), href: '/articles' },
{ icon: 'fa-folder', text: t('nav.categories'), href: '/categories' },
{ icon: 'fa-user-secret', text: t('nav.about'), href: '/about' },
...(siteSettings.ai.enabled ? [{ icon: 'fa-robot', text: t('nav.ask'), href: '/ask' }] : []),
];
const secondaryQuickLinks = [
{ icon: 'fa-tags', text: t('nav.tags'), href: '/tags' },
{ icon: 'fa-stream', text: t('nav.timeline'), href: '/timeline' },
{ icon: 'fa-star', text: t('nav.reviews'), href: '/reviews' },
{ icon: 'fa-link', text: t('nav.friends'), href: '/friends' },
];
const homeBriefHighlights = buildDiscoveryHighlights([
siteSettings.siteDescription,
siteSettings.heroSubtitle,
@@ -609,18 +616,18 @@ const homeFaqJsonLd = buildFaqJsonLd(homeFaqs);
</div>
</div>
<aside class="home-sidebar-stack xl:sticky xl:top-24 xl:self-start">
<section class="terminal-panel home-sidebar-card space-y-4">
<aside class="home-sidebar-stack">
<section class="terminal-panel home-sidebar-card home-sidebar-card--quickmenu space-y-4 xl:sticky xl:top-24">
<div class="space-y-1">
<span class="terminal-kicker w-fit">
<i class="fas fa-compass"></i>
side nav
quick menu
</span>
<h3 class="text-lg font-semibold text-[var(--title-color)]">{homeSidebarCopy.quickLinks}</h3>
<p class="text-sm leading-6 text-[var(--text-secondary)]">{homeSidebarCopy.quickLinksDesc}</p>
</div>
<div class="home-sidebar-grid">
{navLinks.map(link => (
{primaryQuickLinks.map(link => (
<a
href={link.href}
class="home-sidebar-link group flex min-w-0 items-center gap-3 rounded-2xl border border-[var(--border-color)] bg-[var(--terminal-bg)]/75 px-3 py-2.5 text-sm text-[var(--title-color)] transition hover:-translate-y-0.5 hover:border-[var(--primary)] hover:text-[var(--primary)]"
@@ -633,11 +640,29 @@ const homeFaqJsonLd = buildFaqJsonLd(homeFaqs);
</a>
))}
</div>
<div class="space-y-1 border-t border-[color:color-mix(in_oklab,var(--primary)_10%,var(--border-color))] pt-4">
<h4 class="text-sm font-semibold text-[var(--title-color)]">{homeSidebarCopy.quickLinksMore}</h4>
</div>
<div class="grid gap-2 sm:grid-cols-2 xl:grid-cols-2">
{secondaryQuickLinks.map(link => (
<a
href={link.href}
class="home-sidebar-mini-link group flex min-w-0 items-center gap-2.5 rounded-xl border border-[var(--border-color)] bg-[var(--terminal-bg)]/72 px-3 py-2 text-xs text-[var(--text-secondary)] transition hover:-translate-y-0.5 hover:border-[var(--primary)] hover:text-[var(--primary)]"
>
<span class="home-sidebar-mini-link__icon">
<i class={`fas ${link.icon} text-[10px]`}></i>
</span>
<span class="min-w-0 flex-1 truncate font-medium">{link.text}</span>
</a>
))}
</div>
</section>
<SharePanel
shareTitle={siteSettings.siteTitle}
summary={siteSettings.heroSubtitle || siteSettings.siteDescription}
summary={homeShareSummary}
canonicalUrl={siteBaseUrl}
badge={homeShareCopy.badge}
title={homeShareCopy.title}
@@ -737,22 +762,22 @@ const homeFaqJsonLd = buildFaqJsonLd(homeFaqs);
</div>
<div class="grid gap-3 sm:grid-cols-2 xl:grid-cols-2">
<div class="home-sidebar-stat home-sidebar-stat--metric rounded-2xl border border-[var(--border-color)] bg-[var(--bg)]/70 p-4">
<div class="home-sidebar-stat home-sidebar-stat--metric rounded-2xl border border-[color:color-mix(in_oklab,var(--primary)_10%,var(--border-color))] p-4">
<p class="text-xs uppercase tracking-[0.18em] text-[var(--text-tertiary)]">{t('home.views')}</p>
<p id="home-reading-views-value" class="mt-3 text-2xl font-semibold text-[var(--title-color)]">{activeContentRange.overview.pageViews}</p>
<p class="mt-2 text-xs text-[var(--text-secondary)]">{t('home.totalViews')}: {contentOverview.totalPageViews}</p>
</div>
<div class="home-sidebar-stat home-sidebar-stat--metric rounded-2xl border border-[var(--border-color)] bg-[var(--bg)]/70 p-4">
<div class="home-sidebar-stat home-sidebar-stat--metric rounded-2xl border border-[color:color-mix(in_oklab,var(--primary)_10%,var(--border-color))] p-4">
<p class="text-xs uppercase tracking-[0.18em] text-[var(--text-tertiary)]">{t('home.completes')}</p>
<p id="home-reading-completes-value" class="mt-3 text-2xl font-semibold text-[var(--title-color)]">{activeContentRange.overview.readCompletes}</p>
<p class="mt-2 text-xs text-[var(--text-secondary)]">{t('home.totalCompletes')}: {contentOverview.totalReadCompletes}</p>
</div>
<div class="home-sidebar-stat home-sidebar-stat--metric rounded-2xl border border-[var(--border-color)] bg-[var(--bg)]/70 p-4">
<div class="home-sidebar-stat home-sidebar-stat--metric rounded-2xl border border-[color:color-mix(in_oklab,var(--primary)_10%,var(--border-color))] p-4">
<p class="text-xs uppercase tracking-[0.18em] text-[var(--text-tertiary)]">{t('home.avgProgress')}</p>
<p id="home-reading-progress-value" class="mt-3 text-2xl font-semibold text-[var(--title-color)]">{formatProgressPercent(activeContentRange.overview.avgReadProgress)}</p>
<p id="home-reading-window-meta" class="mt-2 text-xs text-[var(--text-secondary)]">{t('home.statsWindowLabel', { label: activeContentRange.label })}</p>
</div>
<div class="home-sidebar-stat home-sidebar-stat--metric rounded-2xl border border-[var(--border-color)] bg-[var(--bg)]/70 p-4">
<div class="home-sidebar-stat home-sidebar-stat--metric rounded-2xl border border-[color:color-mix(in_oklab,var(--primary)_10%,var(--border-color))] p-4">
<p class="text-xs uppercase tracking-[0.18em] text-[var(--text-tertiary)]">{t('home.avgDuration')}</p>
<p id="home-reading-duration-value" class="mt-3 text-2xl font-semibold text-[var(--title-color)]">{formatDurationMs(activeContentRange.overview.avgReadDurationMs)}</p>
<p class="mt-2 text-xs text-[var(--text-secondary)]">{t('common.posts')}: {allPosts.length}</p>
@@ -848,7 +873,7 @@ const homeFaqJsonLd = buildFaqJsonLd(homeFaqs);
<div class="my-8 border-t border-[var(--border-color)]"></div>
<div class="px-4 pb-2">
<div id="site-brief" class="px-4 pb-2">
<div class="ml-4">
<DiscoveryBrief
badge={isEnglish ? 'site brief' : homeSidebarCopy.aiBriefTitle}