diff --git a/src/components/Posts/PostMenu.astro b/src/components/Posts/PostMenu.astro
new file mode 100644
index 0000000..a81e4d8
--- /dev/null
+++ b/src/components/Posts/PostMenu.astro
@@ -0,0 +1,335 @@
+---
+interface Heading {
+ depth: number;
+ slug: string;
+ text: string;
+}
+
+interface Props {
+ headings: Heading[];
+}
+
+const { headings = [] } = Astro.props;
+
+// 只取 h2 / h3,博客目录最常见
+const tocHeadings = headings.filter((h) => h.depth === 2 || h.depth === 3);
+
+// 手机端按钮里显示的“目录: 第一节、xxxxx”
+const mobilePreview = tocHeadings[0]?.text ?? "本文目录";
+---
+
+{
+ tocHeadings.length > 0 && (
+ <>
+
+
+
+ >
+ )
+}
+
+
+
+
+
+
diff --git a/src/layouts/MarkdownPostLayout.astro b/src/layouts/MarkdownPostLayout.astro
index 4c45f43..9ea5aa0 100644
--- a/src/layouts/MarkdownPostLayout.astro
+++ b/src/layouts/MarkdownPostLayout.astro
@@ -2,11 +2,12 @@
import BaseLayout from "./BaseLayout.astro";
import Remark42Embed from "@/components/Remark42Embed.astro";
import PostNav from "@/components/Posts/PostNav.astro";
+import PostMenu from "@/components/Posts/PostMenu.astro";
import { fade } from "astro:transitions";
import { getTranslations } from "@/i18n";
import "@/styles/global.css";
-const { post, frontmatter, lang, slug, postId } = Astro.props;
+const { post, frontmatter, lang, slug, postId, headings } = Astro.props;
const comments = lang === "zh" ? "评论区" : "comments";
const t = getTranslations(lang);
---
@@ -38,6 +39,9 @@ const t = getTranslations(lang);
+
+
+