956 字
5 分钟Add commentMore actions
Fuwari添加系列栏
示例
---title: Fuwari添加系列栏published: 2025-06-16description: "静态博客养成计划"image: ""tags: ["Fuwari", "教程"]category: Guidesdraft: falsepinned: truecomments: falseseries: "博客改造计划"---
添加系列功能
添加 series 字段
export type BlogPostData = {12 collapsed lines
body: string; title: string; published: Date; description: string; tags: string[]; draft?: boolean; image?: string; category?: string; prevTitle?: string; prevSlug?: string; nextTitle?: string; nextSlug?: string; comments?: boolean; pinned?: boolean; series?:string;};
const postsCollection = defineCollection({9 collapsed lines
schema: z.object({ title: z.string(), published: z.date(), updated: z.date().optional(), draft: z.boolean().optional().default(false), description: z.string().optional().default(""), image: z.string().optional().default(""), tags: z.array(z.string()).optional().default([]), category: z.string().optional().default(""), lang: z.string().optional().default(""), comments: z.boolean().optional().default(false), pinned: z.boolean().optional().default(false), series: z.string().optional(),
10 collapsed lines
/* For internal use */ prevTitle: z.string().default(""), prevSlug: z.string().default(""), nextTitle: z.string().default(""), nextSlug: z.string().default(""), }),});export const collections = { posts: postsCollection,};
interface Props { title?: string; banner?: string; description?: string; lang?: string; setOGTypeArticle?: boolean; headings?: MarkdownHeading[]; series?: string;}
const { title, banner, description, lang, setOGTypeArticle, headings = [], series,} = Astro.props;
国际化i18n翻译
修改 📁i18n
里的文件,添加 series Key 并修改语言文件中的系列翻译以支持国际化
enum I18nKey {30 collapsed lines
home = "home", about = "about", archive = "archive", search = "search",
tags = "tags", categories = "categories", recentPosts = "recentPosts",
comments = "comments",
untitled = "untitled", uncategorized = "uncategorized", noTags = "noTags",
wordCount = "wordCount", wordsCount = "wordsCount", minuteCount = "minuteCount", minutesCount = "minutesCount", postCount = "postCount", postsCount = "postsCount",
themeColor = "themeColor",
lightMode = "lightMode", darkMode = "darkMode", systemMode = "systemMode",
more = "more",
author = "author", publishedAt = "publishedAt", license = "license", friends = "friends", series = "series",}
以 src\i18n\languages\zh_CN.ts
为例,修改成对应语言即可
export const zh_CN: Translation = {32 collapsed lines
[Key.home]: "主页", [Key.about]: "关于", [Key.archive]: "归档", [Key.search]: "搜索",
[Key.tags]: "标签", [Key.categories]: "分类", [Key.recentPosts]: "最新文章",
[Key.comments]: "评论",
[Key.untitled]: "无标题", [Key.uncategorized]: "未分类", [Key.noTags]: "无标签",
[Key.wordCount]: "字", [Key.wordsCount]: "字", [Key.minuteCount]: "分钟", [Key.minutesCount]: "分钟", [Key.postCount]: "篇文章", [Key.postsCount]: "篇文章",
[Key.themeColor]: "主题色",
[Key.lightMode]: "亮色", [Key.darkMode]: "暗色", [Key.systemMode]: "跟随系统",
[Key.more]: "更多",
[Key.author]: "作者", [Key.publishedAt]: "发布于", [Key.license]: "许可协议", [Key.friends]: "友链", [Key.series]: "系列",};
添加 series 组件
修改 MainGridLayout 组件
修改 MainGridLayout
组件,接收 series 并将其传入 SideBar
组件
<SideBar class="mb-4 row-start-2 row-end-3 col-span-2 lg:row-start-1 lg:row-end-2 lg:col-span-1 lg:max-w-[17.5rem] onload-animation" headings={headings} series={ series }></SideBar>
修改 […slug] 页面
将 series
传入[...slug].astro
的 MainGridLayout
组件:
<MainGridLayout banner={entry.data.image} title={entry.data.title} description={entry.data.description} lang={entry.data.lang} setOGTypeArticle={true} series={entry.data.series}></MainGridLayout>
添加 getPostSeries 方法
在 content-utils.ts
末尾处添加 getPostSeries
方法:
export async function getPostSeries( seriesName: string,): Promise<{ body: string; data: BlogPostData; slug: string }[]> { const posts = (await getCollection('posts', ({ data }) => { return ( (import.meta.env.PROD ? data.draft !== true : true) && data.series === seriesName ) })) as unknown as { body: string; data: BlogPostData; slug: string }[]
posts.sort((a, b) => { const dateA = new Date(a.data.published) const dateB = new Date(b.data.published) return dateA > dateB ? 1 : -1 })
return posts}
创建 series 组件
---import I18nKey from '../../i18n/i18nKey'import { i18n } from '../../i18n/translation'import { getPostSeries } from '../../utils/content-utils'import { getPostUrlBySlug } from '../../utils/url-utils'import WidgetLayout from './WidgetLayout.astro'
const COLLAPSED_HEIGHT = '7.5rem'
interface Props { class?: string style?: string series: string}const className = Astro.props.classconst style = Astro.props.styleconst seriesName = Astro.props.series
const series = await getPostSeries(seriesName)
const isCollapsed = series.length >= 10---<WidgetLayout name={i18n(I18nKey.series) + " - " + series[0].data.series} id="series" isCollapsed={isCollapsed} collapsedHeight={COLLAPSED_HEIGHT} class={className} style={style}> <div class="flex flex-col gap-1"> {series.map(t => ( <a href={getPostUrlBySlug(t.slug)} aria-label={t.data.title} class="group btn-plain h-10 w-full rounded-lg hover:text-[initial]" > <!-- dot and line --> <div class="w-[15%] md:w-[10%] relative dash-line h-full flex items-center"> <div class="transition-all mx-auto w-1 h-1 rounded group-hover:h-5 bg-[oklch(0.5_0.05_var(--hue))] group-hover:bg-[var(--primary)] outline outline-4 z-50 outline-[var(--card-bg)] group-hover:outline-[var(--btn-plain-bg-hover)] group-active:outline-[var(--btn-plain-bg-active)] " ></div> </div> <!-- post title --> <div class="w-[85%] text-left font-bold group-hover:translate-x-1 transition-all group-hover:text-[var(--primary)] text-75 pr-15 whitespace-nowrap overflow-ellipsis overflow-hidden" title={t.data.title} > {t.data.title} </div> </a> ))} </div></WidgetLayout>
导入 series 组件
在SideBar组件中导入Series组件,接收series并将其传入Series组件
---import type { MarkdownHeading } from "astro";import Categories from "./Categories.astro";import Profile from "./Profile.astro";import Series from "./Series.astro";import Tag from "./Tags.astro";
interface Props { class?: string; headings?: MarkdownHeading[]; series?: string;}
const className = Astro.props.class;
const series = Astro.props.series;---<div id="sidebar" class:list={[className, "w-full"]}> <div class="flex flex-col w-full gap-4 mb-4"> <Profile></Profile> </div> <div id="sidebar-sticky" class="transition-all duration-700 flex flex-col w-full gap-4 top-4 sticky "> <div id="series" class="flex flex-col w-full gap-4"> { series && <Series series={ series }></Series> } </div> <Categories class="onload-animation" style="animation-delay: 150ms"></Categories> <Tag class="onload-animation" style="animation-delay: 200ms"></Tag> </div></div>
在 swup 的 containers 配置项里加上 #series
:
swup({ theme: false, animationClass: "transition-swup-", // see https://swup.js.org/options/#animationselector // the default value `transition-` cause transition delay // when the Tailwind class `transition-all` is used containers: ["main", "#toc", "#series"], smoothScrolling: true, cache: true, preload: true, accessibility: true, updateHead: true, updateBodyClass: false, globalInstance: true,}),
使用系列功能
只需要在md文件frontmatter配置项中添加series,只要系列名相同就会被归类为同一系列
Fuwari添加系列栏
https://p1ume.vercel.app/posts/fuwari/series/