Unify homepage panels and subscription actions
Some checks failed
docker-images / resolve-build-targets (push) Successful in 5s
ui-regression / playwright-regression (push) Failing after 11m59s
docker-images / build-and-push (admin) (push) Successful in 3s
docker-images / build-and-push (backend) (push) Successful in 3s
docker-images / build-and-push (frontend) (push) Successful in 58s
docker-images / submit-indexnow (push) Successful in 18s
Some checks failed
docker-images / resolve-build-targets (push) Successful in 5s
ui-regression / playwright-regression (push) Failing after 11m59s
docker-images / build-and-push (admin) (push) Successful in 3s
docker-images / build-and-push (backend) (push) Successful in 3s
docker-images / build-and-push (frontend) (push) Successful in 58s
docker-images / submit-indexnow (push) Successful in 18s
This commit is contained in:
@@ -10,10 +10,10 @@ const { stats } = Astro.props;
|
||||
|
||||
<ul class="grid gap-3">
|
||||
{stats.map((stat, index) => (
|
||||
<li class="rounded-2xl border border-[var(--border-color)] bg-[linear-gradient(135deg,rgba(var(--primary-rgb),0.12),rgba(255,255,255,0.55))] px-4 py-4 shadow-[0_12px_32px_rgba(37,99,235,0.08)]">
|
||||
<li class="terminal-panel-muted terminal-panel-accent terminal-interactive-card rounded-2xl px-4 py-4" style="--accent-rgb: var(--primary-rgb); --accent-color: var(--primary);">
|
||||
<div class="flex items-center justify-between gap-4">
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-transparent bg-[var(--primary)] text-[var(--terminal-bg)] shadow-[0_10px_24px_rgba(var(--primary-rgb),0.22)]">
|
||||
<span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-[color:color-mix(in_oklab,var(--primary)_16%,var(--border-color))] bg-[linear-gradient(180deg,color-mix(in_oklab,var(--primary)_18%,var(--terminal-bg)),color-mix(in_oklab,var(--primary)_10%,var(--header-bg)))] text-[var(--primary)] shadow-[0_10px_24px_rgba(var(--text-rgb),0.06)]">
|
||||
<span class="font-mono text-xs">{String(index + 1).padStart(2, '0')}</span>
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
@@ -21,7 +21,7 @@ const { stats } = Astro.props;
|
||||
<div class="mt-1 text-lg font-semibold text-[var(--title-color)]">{stat.value}</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="h-10 w-px bg-[linear-gradient(180deg,transparent,rgba(var(--primary-rgb),0.3),transparent)]"></span>
|
||||
<span class="h-10 w-px bg-[linear-gradient(180deg,transparent,rgba(var(--primary-rgb),0.22),transparent)]"></span>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
|
||||
@@ -155,13 +155,31 @@ const webPushAvailable = Boolean(webPushPublicKey);
|
||||
<i class="fas fa-envelope-open-text"></i>
|
||||
</span>
|
||||
<span class="subscription-popup-channel-toggle-copy">
|
||||
<span class="subscription-popup-channel-toggle-meta" aria-hidden="true">
|
||||
<span class="subscription-popup-channel-toggle-tag">可选</span>
|
||||
<span class="subscription-popup-channel-toggle-tag subscription-popup-channel-toggle-tag--email">
|
||||
Email
|
||||
</span>
|
||||
</span>
|
||||
<span class="subscription-popup-channel-toggle-title" data-subscription-popup-channel-toggle-label>
|
||||
开启邮件订阅
|
||||
添加邮件订阅
|
||||
</span>
|
||||
<span class="subscription-popup-channel-toggle-description">
|
||||
需要时再补一个邮箱备份
|
||||
<span
|
||||
class="subscription-popup-channel-toggle-description"
|
||||
data-subscription-popup-channel-toggle-description
|
||||
>
|
||||
填写邮箱后,更新也会发到你的收件箱
|
||||
</span>
|
||||
</span>
|
||||
<span class="subscription-popup-channel-toggle-affordance" aria-hidden="true">
|
||||
<span
|
||||
class="subscription-popup-channel-toggle-affordance-text"
|
||||
data-subscription-popup-channel-toggle-affordance
|
||||
>
|
||||
去填写
|
||||
</span>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -376,6 +394,12 @@ const webPushAvailable = Boolean(webPushPublicKey);
|
||||
const emailToggleLabel = emailToggleButton?.querySelector(
|
||||
'[data-subscription-popup-channel-toggle-label]',
|
||||
) as HTMLElement | null;
|
||||
const emailToggleDescription = emailToggleButton?.querySelector(
|
||||
'[data-subscription-popup-channel-toggle-description]',
|
||||
) as HTMLElement | null;
|
||||
const emailToggleAffordance = emailToggleButton?.querySelector(
|
||||
'[data-subscription-popup-channel-toggle-affordance]',
|
||||
) as HTMLElement | null;
|
||||
const browserCard = root.querySelector(
|
||||
'[data-subscription-popup-channel-card="browser"]',
|
||||
) as HTMLElement | null;
|
||||
@@ -572,7 +596,17 @@ const webPushAvailable = Boolean(webPushPublicKey);
|
||||
emailInput.required = emailSelected;
|
||||
|
||||
if (emailToggleLabel instanceof HTMLElement) {
|
||||
emailToggleLabel.textContent = emailSelected ? '收起邮件订阅' : '开启邮件订阅';
|
||||
emailToggleLabel.textContent = emailSelected ? '收起邮件订阅' : '添加邮件订阅';
|
||||
}
|
||||
|
||||
if (emailToggleDescription instanceof HTMLElement) {
|
||||
emailToggleDescription.textContent = emailSelected
|
||||
? '邮箱表单已经展开,填好后提交即可作为额外备份'
|
||||
: '填写邮箱后,更新也会发到你的收件箱';
|
||||
}
|
||||
|
||||
if (emailToggleAffordance instanceof HTMLElement) {
|
||||
emailToggleAffordance.textContent = emailSelected ? '收起' : '去填写';
|
||||
}
|
||||
|
||||
setToggleState(emailToggleButton, emailSelected, !browserRequired);
|
||||
@@ -1210,6 +1244,43 @@ const webPushAvailable = Boolean(webPushPublicKey);
|
||||
display: grid;
|
||||
gap: 0.18rem;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle-meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.35rem;
|
||||
margin-bottom: 0.1rem;
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border-radius: 999px;
|
||||
border: 1px solid color-mix(in oklab, var(--border-color) 88%, transparent);
|
||||
background: color-mix(in oklab, var(--header-bg) 84%, transparent);
|
||||
color: var(--text-tertiary);
|
||||
padding: 0.15rem 0.45rem;
|
||||
font-size: 0.66rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle-tag--email {
|
||||
color: color-mix(in oklab, var(--secondary, var(--primary)) 62%, var(--title-color));
|
||||
border-color: color-mix(
|
||||
in oklab,
|
||||
var(--secondary, var(--primary)) 22%,
|
||||
var(--border-color)
|
||||
);
|
||||
background: color-mix(
|
||||
in oklab,
|
||||
var(--secondary, var(--primary)) 11%,
|
||||
var(--terminal-bg)
|
||||
);
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle-title {
|
||||
@@ -1227,6 +1298,27 @@ const webPushAvailable = Boolean(webPushPublicKey);
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle-affordance {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
margin-left: auto;
|
||||
align-self: center;
|
||||
color: color-mix(in oklab, var(--secondary, var(--primary)) 58%, var(--title-color));
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
transition:
|
||||
color 0.2s ease,
|
||||
transform 0.2s ease;
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle-affordance i {
|
||||
font-size: 0.72rem;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle:hover {
|
||||
transform: translateY(-1px);
|
||||
border-color: color-mix(in oklab, var(--primary) 22%, var(--border-color));
|
||||
@@ -1234,6 +1326,10 @@ const webPushAvailable = Boolean(webPushPublicKey);
|
||||
box-shadow: 0 14px 28px rgba(var(--text-rgb), 0.08);
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle:hover .subscription-popup-channel-toggle-affordance {
|
||||
transform: translateX(1px);
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle.is-active {
|
||||
border-color: color-mix(in oklab, var(--primary) 28%, var(--border-color));
|
||||
background:
|
||||
@@ -1252,6 +1348,10 @@ const webPushAvailable = Boolean(webPushPublicKey);
|
||||
background: color-mix(in oklab, var(--primary) 16%, var(--terminal-bg));
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle.is-active .subscription-popup-channel-toggle-affordance i {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.subscription-popup-channel-toggle--primary {
|
||||
border-color: color-mix(in oklab, var(--primary) 48%, var(--border-color));
|
||||
background:
|
||||
|
||||
@@ -10,9 +10,9 @@ const { items } = Astro.props;
|
||||
|
||||
<ul class="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
||||
{items.map((item) => (
|
||||
<li class="group overflow-hidden rounded-2xl border border-[var(--border-color)] bg-[var(--terminal-bg)] shadow-[0_12px_30px_rgba(37,99,235,0.08)] transition-transform duration-200 hover:-translate-y-0.5">
|
||||
<li class="terminal-panel-muted terminal-panel-accent terminal-interactive-card group overflow-hidden rounded-2xl" style="--accent-rgb: var(--primary-rgb); --accent-color: var(--primary);">
|
||||
<div class="flex items-start gap-3 px-4 py-4">
|
||||
<span class="mt-0.5 flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-[var(--primary)] text-white shadow-[0_10px_24px_rgba(37,99,235,0.24)]">
|
||||
<span class="mt-0.5 flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-[color:color-mix(in_oklab,var(--primary)_14%,var(--border-color))] bg-[linear-gradient(180deg,color-mix(in_oklab,var(--primary)_16%,var(--terminal-bg)),color-mix(in_oklab,var(--primary)_9%,var(--header-bg)))] text-[var(--primary)] shadow-[0_10px_24px_rgba(var(--text-rgb),0.06)]">
|
||||
<i class="fas fa-code text-xs"></i>
|
||||
</span>
|
||||
<span class="min-w-0 flex-1">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -284,6 +284,17 @@ const homeSidebarCopy = isEnglish
|
||||
statsDesc: '轻量围观一下站内气氛,不必知道太多。',
|
||||
aiBriefTitle: '站点便签',
|
||||
};
|
||||
const homeAboutSectionCopy = isEnglish
|
||||
? {
|
||||
techDesc: 'The main tools and frameworks currently carrying the site and its content flow.',
|
||||
metricsDesc: 'Site scale and basic signals, shown with the same terminal panel language as the rest of the page.',
|
||||
apiAlert: 'home / api alert',
|
||||
}
|
||||
: {
|
||||
techDesc: '当前页面和内容背后常用的技术组合。',
|
||||
metricsDesc: '用同一套终端面板看站内规模,不再突然切回普通信息块。',
|
||||
apiAlert: 'home / api alert',
|
||||
};
|
||||
const primaryQuickLinks = [
|
||||
{ icon: 'fa-file-code', text: t('nav.articles'), href: '/articles' },
|
||||
{ icon: 'fa-folder', text: t('nav.categories'), href: '/categories' },
|
||||
@@ -385,8 +396,14 @@ const homeFaqJsonLd = buildFaqJsonLd(homeFaqs);
|
||||
|
||||
{apiError && (
|
||||
<div class="mb-8 px-4">
|
||||
<div class="ml-4 p-4 rounded-lg border border-[var(--danger)]/20 bg-[var(--danger)]/10 text-[var(--danger)] text-sm">
|
||||
{apiError}
|
||||
<div class="terminal-panel-muted ml-4 flex items-start gap-3 border-[color:color-mix(in_oklab,var(--danger)_24%,var(--border-color))] bg-[linear-gradient(180deg,color-mix(in_oklab,var(--danger)_8%,var(--terminal-bg)),color-mix(in_oklab,var(--danger)_4%,var(--header-bg)))] px-4 py-4 text-sm text-[var(--danger)]">
|
||||
<span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-[color:color-mix(in_oklab,var(--danger)_24%,var(--border-color))] bg-[color:color-mix(in_oklab,var(--danger)_12%,var(--terminal-bg))]">
|
||||
<i class="fas fa-triangle-exclamation"></i>
|
||||
</span>
|
||||
<div class="min-w-0 space-y-1">
|
||||
<p class="text-[11px] font-mono uppercase tracking-[0.2em] text-[var(--text-tertiary)]">{homeAboutSectionCopy.apiAlert}</p>
|
||||
<p class="leading-7 text-[var(--danger)]">{apiError}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -854,20 +871,55 @@ const homeFaqJsonLd = buildFaqJsonLd(homeFaqs);
|
||||
<div id="about" class="px-4">
|
||||
<CommandPrompt command={t('home.promptAbout')} />
|
||||
<div class="ml-4">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div class="grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1.22fr)_minmax(18rem,0.78fr)]">
|
||||
<section class="terminal-panel space-y-5">
|
||||
<div class="flex flex-wrap items-start justify-between gap-4">
|
||||
<div class="space-y-2">
|
||||
<span class="terminal-kicker w-fit">
|
||||
<i class="fas fa-user-astronaut"></i>
|
||||
home / profile
|
||||
</span>
|
||||
<div>
|
||||
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">{t('home.about')}</h3>
|
||||
<p class="text-[var(--text-secondary)] mb-4">{siteSettings.ownerBio}</p>
|
||||
<h3 class="text-xl font-bold text-[var(--title-color)]">{t('home.about')}</h3>
|
||||
<p class="mt-2 max-w-3xl text-sm leading-7 text-[var(--text-secondary)]">{siteSettings.ownerBio}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">{t('home.techStack')}</h3>
|
||||
<span class="terminal-stat-pill">
|
||||
<i class="fas fa-code-branch text-[var(--primary)]"></i>
|
||||
{t('common.postsCount', { count: allPosts.length })}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="terminal-section-icon">
|
||||
<i class="fas fa-layer-group"></i>
|
||||
</span>
|
||||
<div>
|
||||
<h4 class="text-base font-semibold text-[var(--title-color)]">{t('home.techStack')}</h4>
|
||||
<p class="text-sm text-[var(--text-secondary)]">{homeAboutSectionCopy.techDesc}</p>
|
||||
</div>
|
||||
</div>
|
||||
<TechStackList items={techStack} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="terminal-panel space-y-4">
|
||||
<div class="space-y-2">
|
||||
<span class="terminal-kicker w-fit">
|
||||
<i class="fas fa-chart-column"></i>
|
||||
home / metrics
|
||||
</span>
|
||||
<div>
|
||||
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">{t('home.systemStatus')}</h3>
|
||||
<StatsList stats={systemStats} />
|
||||
<h3 class="text-xl font-bold text-[var(--title-color)]">{t('home.systemStatus')}</h3>
|
||||
<p class="mt-2 text-sm leading-7 text-[var(--text-secondary)]">{homeAboutSectionCopy.metricsDesc}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<StatsList stats={systemStats} />
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user