修复文章所有的问题

This commit is contained in:
lsy 2025-03-10 14:05:40 +08:00
parent ab83710eb6
commit 9ed938c946
3 changed files with 104 additions and 107 deletions

View File

@ -1,94 +0,0 @@
---
import type { CollectionEntry } from 'astro:content';
interface Props {
title?: string;
articles: CollectionEntry<'articles'>[];
}
const {
title = "文章时间线",
articles = []
} = Astro.props;
// 按日期排序文章
const sortedArticles = articles.sort(
(a, b) => b.data.date.getTime() - a.data.date.getTime()
);
---
<div class="container mx-auto px-4 py-8">
{title && <h1 class="text-3xl font-bold mb-6 text-primary-900 dark:text-primary-100">{title}</h1>}
<div id="article-timeline" class="relative space-y-8 before:absolute before:inset-0 before:ml-5 before:h-full before:w-0.5 before:-translate-x-px before:bg-gradient-to-b before:from-transparent before:via-primary-300 before:to-transparent md:before:mx-auto md:before:translate-x-0">
{sortedArticles.length > 0 ? (
sortedArticles.map((article, index) => {
const isEven = index % 2 === 0;
return (
<div class="relative group">
{/* 时间线节点 */}
<div class="absolute left-5 -translate-x-1/2 md:left-1/2 top-6 flex h-3 w-3 items-center justify-center">
<div class="h-2 w-2 rounded-full bg-primary-500 dark:bg-primary-400 ring-2 ring-white dark:ring-gray-900 ring-offset-2 ring-offset-white dark:ring-offset-gray-900"></div>
</div>
{/* 文章卡片 */}
<a href={`/articles/${article.id}`}
class={`group/card ml-10 md:ml-0 ${isEven ? 'md:mr-[50%] md:pr-8' : 'md:ml-[50%] md:pl-8'} block`}>
<article class="relative flex flex-col gap-4 rounded-xl bg-white dark:bg-gray-800 p-6 shadow-lg hover:shadow-xl hover:-translate-y-1 transition-all duration-300 border border-gray-200 dark:border-gray-700">
{/* 日期标签 */}
<time datetime={article.data.date.toISOString()}
class="absolute top-4 right-4 text-xs font-medium text-secondary-500 dark:text-secondary-400">
{article.data.date.toLocaleDateString('zh-CN', {year: 'numeric', month: 'long', day: 'numeric'})}
</time>
{/* 文章标题 */}
<h3 class="pr-16 text-xl font-bold text-gray-900 dark:text-gray-100 group-hover/card:text-primary-600 dark:group-hover/card:text-primary-400 transition-colors">
{article.data.title}
</h3>
{/* 文章摘要 */}
{article.data.summary && (
<p class="text-secondary-600 dark:text-secondary-300 line-clamp-2">
{article.data.summary}
</p>
)}
{/* 文章元信息 */}
<div class="flex flex-wrap items-center gap-4 text-sm">
{article.data.section && (
<span class="flex items-center text-secondary-500 dark:text-secondary-400">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
</svg>
{article.data.section}
</span>
)}
{article.data.tags && article.data.tags.length > 0 && (
<div class="flex flex-wrap gap-2">
{article.data.tags.map(tag => (
<span class="text-xs bg-primary-50 dark:bg-primary-900/30 text-primary-600 dark:text-primary-400 py-1 px-2 rounded-full">
#{tag}
</span>
))}
</div>
)}
</div>
{/* 阅读更多指示器 */}
<div class="flex items-center text-sm text-primary-600 dark:text-primary-400 group-hover/card:translate-x-1 transition-transform">
<span class="font-medium">阅读全文</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
</svg>
</div>
</article>
</a>
</div>
);
})
) : (
<div class="text-center py-4 text-secondary-600 dark:text-secondary-400">暂无文章数据</div>
)}
</div>
</div>

View File

@ -1,6 +1,6 @@
--- ---
import { getCollection, render } from 'astro:content'; import { getCollection, render } from 'astro:content';
import { contentStructure, getRelativePath, getBasename, getDirPath, getOriginalPath, getSpecialPath } from '@/content.config'; import { contentStructure, getRelativePath, getBasename, getDirPath, getSpecialPath } from '@/content.config';
import type { SectionStructure } from '@/content.config'; import type { SectionStructure } from '@/content.config';
import Layout from '@/components/Layout.astro'; import Layout from '@/components/Layout.astro';
import Breadcrumb from '@/components/Breadcrumb.astro'; import Breadcrumb from '@/components/Breadcrumb.astro';
@ -10,6 +10,7 @@ export const prerender = true;
export async function getStaticPaths() { export async function getStaticPaths() {
const articles = await getCollection('articles'); const articles = await getCollection('articles');
const views = ['grid', 'timeline'];
// 为每篇文章添加section信息 // 为每篇文章添加section信息
const articlesWithSections = articles.map(article => { const articlesWithSections = articles.map(article => {
@ -67,23 +68,41 @@ export async function getStaticPaths() {
}); });
// 为每篇文章生成路由参数 // 为每篇文章生成路由参数
return articlesWithSections.map(article => { const paths = [];
for (const article of articlesWithSections) {
// 检查文章ID是否需要特殊处理 // 检查文章ID是否需要特殊处理
const specialId = getSpecialPath(article.id); const specialId = getSpecialPath(article.id);
return { // 添加基本路由
paths.push({
params: { id: specialId }, params: { id: specialId },
props: { props: {
article, article,
section: article.section, section: article.section,
originalId: specialId !== article.id ? article.id : undefined originalId: specialId !== article.id ? article.id : undefined,
view: undefined
} }
}; });
});
// 为每个视图添加路由
for (const view of views) {
paths.push({
params: { id: `${specialId}/${view}` },
props: {
article,
section: article.section,
originalId: specialId !== article.id ? article.id : undefined,
view
}
});
}
}
return paths;
} }
// 获取文章内容 // 获取文章内容
const { article, section, originalId } = Astro.props; const { article, section, originalId, view } = Astro.props;
// 如果有原始ID使用它来渲染内容 // 如果有原始ID使用它来渲染内容
const articleToRender = originalId ? { ...article, id: originalId } : article; const articleToRender = originalId ? { ...article, id: originalId } : article;
@ -108,7 +127,7 @@ const description = article.data.summary || `${article.data.title} - 发布于 $
// 处理特殊ID的函数 // 处理特殊ID的函数
function getArticleUrl(articleId: string) { function getArticleUrl(articleId: string) {
return `/articles/${getSpecialPath(articleId)}`; return `/articles/${getSpecialPath(articleId)}${view ? `/${view}` : ''}`;
} }
--- ---
@ -139,7 +158,7 @@ function getArticleUrl(articleId: string) {
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
{/* 返回按钮 */} {/* 返回按钮 */}
<a href="/articles" class="text-secondary-500 dark:text-secondary-400 hover:text-primary-600 dark:hover:text-primary-400 transition-colors flex items-center text-sm"> <a href={`/articles${view ? `/${view}` : ''}`} class="text-secondary-500 dark:text-secondary-400 hover:text-primary-600 dark:hover:text-primary-400 transition-colors flex items-center text-sm">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg> </svg>

View File

@ -4,7 +4,6 @@ import type { CollectionEntry } from 'astro:content';
import { contentStructure } from '../../content.config'; import { contentStructure } from '../../content.config';
import Layout from '@/components/Layout.astro'; import Layout from '@/components/Layout.astro';
import Breadcrumb from '@/components/Breadcrumb.astro'; import Breadcrumb from '@/components/Breadcrumb.astro';
import ArticleTimeline from '@/components/ArticleTimeline.astro';
// 启用静态预渲染 // 启用静态预渲染
export const prerender = true; export const prerender = true;
@ -194,7 +193,7 @@ interface Breadcrumb {
// 处理特殊ID的函数 // 处理特殊ID的函数
function getArticleUrl(articleId: string) { function getArticleUrl(articleId: string) {
return `/articles/${articleId}`; return `/articles/${articleId}${view ? `/${view}` : ''}`;
} }
--- ---
@ -245,7 +244,7 @@ function getArticleUrl(articleId: string) {
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mb-12"> <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mb-12">
{/* 上一级目录卡片 - 仅在浏览目录时显示 */} {/* 上一级目录卡片 - 仅在浏览目录时显示 */}
{!tagFilter && pathSegments.length > 0 && ( {!tagFilter && pathSegments.length > 0 && (
<a href={`/articles/${pathSegments.length > 1 ? pathSegments.slice(0, -1).join('/') : ''}`} <a href={`/articles/${pathSegments.length > 1 ? pathSegments.slice(0, -1).join('/') : ''}/${view}`}
class="group flex flex-col h-full p-5 border border-gray-200 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-800 hover:shadow-xl hover:-translate-y-1 transition-all duration-300 shadow-lg"> class="group flex flex-col h-full p-5 border border-gray-200 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-800 hover:shadow-xl hover:-translate-y-1 transition-all duration-300 shadow-lg">
<div class="flex items-center"> <div class="flex items-center">
<div class="w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600 group-hover:bg-primary-200 transition-colors"> <div class="w-10 h-10 flex items-center justify-center rounded-lg bg-primary-100 text-primary-600 group-hover:bg-primary-200 transition-colors">
@ -447,7 +446,80 @@ function getArticleUrl(articleId: string) {
</div> </div>
</> </>
) : ( ) : (
<ArticleTimeline title="" articles={sortedArticles} /> <div class="container mx-auto px-4 py-8">
{/* 时间线视图 */}
<div id="article-timeline" class="relative space-y-8 before:absolute before:inset-0 before:ml-5 before:h-full before:w-0.5 before:-translate-x-px before:bg-gradient-to-b before:from-transparent before:via-primary-300 before:to-transparent md:before:mx-auto md:before:translate-x-0">
{sortedArticles.length > 0 ? (
sortedArticles.map((article, index) => {
const isEven = index % 2 === 0;
return (
<div class="relative group">
{/* 时间线节点 */}
<div class="absolute left-5 -translate-x-1/2 md:left-1/2 top-6 flex h-3 w-3 items-center justify-center">
<div class="h-2 w-2 rounded-full bg-primary-500 dark:bg-primary-400 ring-2 ring-white dark:ring-gray-900 ring-offset-2 ring-offset-white dark:ring-offset-gray-900"></div>
</div>
{/* 文章卡片 */}
<a href={`/articles/${article.id}${viewMode ? `/${viewMode}` : ''}`}
class={`group/card ml-10 md:ml-0 ${isEven ? 'md:mr-[50%] md:pr-8' : 'md:ml-[50%] md:pl-8'} block`}>
<article class="relative flex flex-col gap-4 rounded-xl bg-white dark:bg-gray-800 p-6 shadow-lg hover:shadow-xl hover:-translate-y-1 transition-all duration-300 border border-gray-200 dark:border-gray-700">
{/* 日期标签 */}
<time datetime={article.data.date.toISOString()}
class="absolute top-4 right-4 text-xs font-medium text-secondary-500 dark:text-secondary-400">
{article.data.date.toLocaleDateString('zh-CN', {year: 'numeric', month: 'long', day: 'numeric'})}
</time>
{/* 文章标题 */}
<h3 class="pr-16 text-xl font-bold text-gray-900 dark:text-gray-100 group-hover/card:text-primary-600 dark:group-hover/card:text-primary-400 transition-colors">
{article.data.title}
</h3>
{/* 文章摘要 */}
{article.body && (
<p class="text-secondary-600 dark:text-secondary-300 line-clamp-2">
{extractSummary(article.body)}
</p>
)}
{/* 文章元信息 */}
<div class="flex flex-wrap items-center gap-4 text-sm">
{article.data.section && (
<span class="flex items-center text-secondary-500 dark:text-secondary-400">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
</svg>
{article.data.section}
</span>
)}
{article.data.tags && article.data.tags.length > 0 && (
<div class="flex flex-wrap gap-2">
{article.data.tags.map(tag => (
<span class="text-xs bg-primary-50 dark:bg-primary-900/30 text-primary-600 dark:text-primary-400 py-1 px-2 rounded-full">
#{tag}
</span>
))}
</div>
)}
</div>
{/* 阅读更多指示器 */}
<div class="flex items-center text-sm text-primary-600 dark:text-primary-400 group-hover/card:translate-x-1 transition-transform">
<span class="font-medium">阅读全文</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
</svg>
</div>
</article>
</a>
</div>
);
})
) : (
<div class="text-center py-4 text-secondary-600 dark:text-secondary-400">暂无文章数据</div>
)}
</div>
</div>
)} )}
</main> </main>
</div> </div>