989 字
5 分钟
增强Fuwari中添加的系统栏
2025-05-16

前提#

你需要遵循教程在Fuwari中添加系列栏 - 伊卡的记事本

添加当前文章被选中效果#

1. 修改Series组件,添加新的Prop和被选中视觉元素#

src\components\widget\Series.astro
---
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;
currentPostTitle?: string;
}
const className = Astro.props.class;
const style = Astro.props.style;
const seriesName = Astro.props.series;
const currentPostTitle = Astro.props.currentPostTitle;
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>
{t.data.title === currentPostTitle && (
<span class="absolute top-1/2 right-1 transform -translate-y-1/2 text-[var(--primary)] transition-all group-hover:translate-x-1">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</span>
)}
</a>
))}
</div>
</WidgetLayout>

其中52-54行是默认的√图像,你可以改成自己喜欢的svg。

2. 修改Sidebar,让当前Post标题能从外部组件流入。#

src\components\widget\SideBar.astro
interface Props {
class?: string;
headings?: MarkdownHeading[];
category?: string;
currentPostTitle?: string;
series?: string;
}
const className = Astro.props.class;
const currentPostTitle = Astro.props.currentPostTitle;
const series = Astro.props.series;
---
<div id="sidebar" class:list={[className, "w-full"]}>
<div class="flex flex-col w-full gap-4">
<ProfileH />
</div>
<div id="sidebar-sticky" class="transition-all duration-700 flex flex-col w-full gap-4 sticky top-4">
<div id="series" class="flex flex-col w-full gap-4">
{ series && <Series series={ series }></Series> }
{ series && <Series series={ series } currentPostTitle={currentPostTitle} class=" mt-4"></Series> }
</div>
<Categories class="onload-animation" style="animation-delay: 150ms"></Categories>
<Tag class="onload-animation" style="animation-delay: 200ms"></Tag>
</div>
</div>

3. 修改[MainGridLayout], 让Post的标题流入Sidebar#

src\layouts\MainGridLayout.astro
interface Props {
currentPostTitle?: string;
title?: string;
banner?: string;
description?: string;
lang?: string;
setOGTypeArticle?: boolean;
headings?: MarkdownHeading[];
series?: string;
}
const {
currentPostTitle,
title,
banner,
description,
lang,
setOGTypeArticle,
headings = [],
series,
} = Astro.props;
<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>
<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} currentPostTitle={currentPostTitle} series={ series }></SideBar>

4. 修改[...slug], 让每个Post的标题流入MainGridLayout#

src\pages\posts[...slug].astro
<MainGridLayout banner={entry.data.image} title={entry.data.title} description={entry.data.description} lang={entry.data.lang} setOGTypeArticle={true} headings={headings} series={entry.data.series}>
<MainGridLayout banner={entry.data.image} title={entry.data.title} description={entry.data.description} lang={entry.data.lang} setOGTypeArticle={true} headings={headings} series={entry.data.series} currentPostTitle={entry.data.title}>

添加时间分隔#

原本的系列栏左侧的时间线仅为装饰,没有显示日期分隔博文的作用,我们可以用日期为博文分组并展示。

1. 安装dayjs#

Day.js 是一个轻量的处理时间和日期的 JavaScript 库,和 Moment.js 的 API 设计保持完全一样。 在命令行中敲入以下指令以在当前项目中安装:

Terminal window
pnpm install dayjs

2. 修改Series组件#

src\components\widget\Series.astro
---
import dayjs from "dayjs";
const seriesPosts = await getPostSeries(seriesName);
// 分组函数
function groupByMonth(
posts: { body: string; data: BlogPostData; slug: string }[],
) {
const groups: {
[key: string]: { body: string; data: BlogPostData; slug: string }[];
} = {};
for (const post of posts) {
// 假设 post.data.date 是 ISO 字符串
const date = dayjs(post.data.published);
const key = `${date.year()}-${date.month() + 1}`; // month() 从0开始
if (!groups[key]) groups[key] = [];
groups[key].push(post);
}
return groups;
}
const grouped = groupByMonth(seriesPosts);
// 生成分组后的数组,方便遍历
const groupedArr = Object.entries(grouped).sort((a, b) =>
b[0].localeCompare(a[0]),
);
---
<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>
{t.data.title === currentPostTitle && (
<span class="absolute top-1/2 right-2 transform -translate-y-1/2 text-[var(--primary)]">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</span>
)}
</a>
))}
{groupedArr.map(([month, posts]) => (
<>
<div class="text-xs text-gray-400 font-semibold my-2">{month}</div>
{posts.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] relative"
>
<!-- 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>
{t.data.title == currentPostTitle && (
<span class="absolute top-1/2 right-2 transform -translate-y-1/2 text-[var(--primary)]">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</span>
)}
</a>
))}
</>
))}
</div>
</WidgetLayout>

修改自动生成脚本#

原本的pnpm new-post "title"命令生成的模板不会自动添加series字段,同时没有填写默认语言。

scripts\new-post.js
const content = `---
title: ${args[0]}
published: ${getDate()}
description: ''
image: ''
tags: []
category: ''
draft: false
series: ''
lang: ''
lang: 'zh_CN'
---
`;
增强Fuwari中添加的系统栏
https://www.raintrap341.com/posts/增强fuwari中添加的系统栏/
作者
RainTrap341
发布于
2025-05-16
许可协议
CC BY-NC-SA 4.0