diff --git a/src/components/Footer.astro b/src/components/Footer.astro
index 8e80bcf..30024a9 100644
--- a/src/components/Footer.astro
+++ b/src/components/Footer.astro
@@ -20,10 +20,6 @@ const locale = propLocale ?? localeOf(Astro.url.pathname);
{t('footer_icp', locale)}
- ·
- {t('footer_stack', locale)}
- ·
- {t('footer_colophon', locale)}
diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro
index 629742a..0f3c529 100644
--- a/src/layouts/BaseLayout.astro
+++ b/src/layouts/BaseLayout.astro
@@ -44,6 +44,22 @@ const withSlash = (p: string) => (p.endsWith('/') ? p : `${p}/`);
{title}
+
@@ -76,6 +92,9 @@ const withSlash = (p: string) => (p.endsWith('/') ? p : `${p}/`);
+
+
跳到正文
diff --git a/src/lib/heartbeat.ts b/src/lib/heartbeat.ts
new file mode 100644
index 0000000..66442f5
--- /dev/null
+++ b/src/lib/heartbeat.ts
@@ -0,0 +1,38 @@
+/**
+ * 首页"最近心跳":构建期拉 blog 仓最新 commit——本站自己的脉搏。
+ * 失败静默(返回 null,首页渲染"很久以前"兜底文案),绝不阻塞构建。
+ */
+export interface Heartbeat {
+ /** commit 首行(截 40 字符) */
+ msg: string;
+ /** commit 时间(ISO) */
+ when: string;
+}
+
+const API = 'https://git.wait4x.online/api/v1/repos/wait4x/blog/commits?limit=1';
+
+export async function fetchHeartbeat(): Promise {
+ try {
+ const res = await fetch(API, {
+ headers: { Accept: 'application/json', 'User-Agent': 'wait4x-blog-build' },
+ signal: AbortSignal.timeout(8_000),
+ });
+ if (!res.ok) return null;
+ const [c] = (await res.json()) as Array<{ commit?: { message?: string; author?: { date?: string } } }>;
+ const msg = c?.commit?.message?.split('\n')[0]?.slice(0, 40);
+ const when = c?.commit?.author?.date;
+ return msg && when ? { msg, when } : null;
+ } catch {
+ return null;
+ }
+}
+
+/** 相对时长(中文短句;en 页由调用方换词条) */
+export function agoZh(iso: string, now = Date.now()): string {
+ const h = Math.floor((now - new Date(iso).getTime()) / 3_600_000);
+ if (h < 1) return '刚刚';
+ if (h < 24) return `${h} 小时前`;
+ const d = Math.floor(h / 24);
+ if (d < 30) return `${d} 天前`;
+ return `${Math.floor(d / 30)} 个月前`;
+}
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 78660df..a1167ca 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -6,6 +6,7 @@ import IdCard from '../components/IdCard.astro';
import PostList from '../components/PostList.astro';
import ProjectWall from '../components/geek/ProjectWall.astro';
import Heatmap from '../components/geek/Heatmap.astro';
+import { fetchHeartbeat, agoZh } from '../lib/heartbeat';
import { t } from '../i18n/ui';
const posts = (await getCollection('posts', ({ data }) => !data.draft && !data.tags.includes('hidden'))).sort(
@@ -13,6 +14,7 @@ const posts = (await getCollection('posts', ({ data }) => !data.draft && !data.t
);
// 最新影像取集合前 4 张;照片时间序由照片管线(exif 车道)治理,此处只裁切
const photos = (await getCollection('photos')).slice(0, 4);
+const heartbeat = await fetchHeartbeat();
---
@@ -99,9 +101,31 @@ const photos = (await getCollection('photos')).slice(0, 4);
}}
/>
+ {heartbeat && (
+
+
+ 最近心跳:{agoZh(heartbeat.when)} · {heartbeat.msg}
+
+ )}