989 字
5 分钟
增强Fuwari中添加的系统栏
前提
你需要遵循教程在Fuwari中添加系列栏 - 伊卡的记事本
添加当前文章被选中效果
1. 修改Series
组件,添加新的Prop和被选中视觉元素
---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标题能从外部组件流入。
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
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
<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 设计保持完全一样。 在命令行中敲入以下指令以在当前项目中安装:
pnpm install dayjs
2. 修改Series
组件
---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
字段,同时没有填写默认语言。
const content = `---title: ${args[0]}published: ${getDate()}description: ''image: ''tags: []category: ''draft: falseseries: ''lang: ''lang: 'zh_CN'---`;
增强Fuwari中添加的系统栏
https://www.raintrap341.com/posts/增强fuwari中添加的系统栏/