--- import { getCollection } from 'astro:content'; import type { CollectionEntry } from 'astro:content'; import { contentStructure, getRelativePath, getBasename, getDirPath } from '../../content.config'; import Layout from '@/components/Layout.astro'; import Breadcrumb from '@/components/Breadcrumb.astro'; import ArticleTimeline from '@/components/ArticleTimeline.astro'; // 预渲染页面,但允许客户端导航 export const prerender = false; // 获取所有文章,并按日期排序 const articles: CollectionEntry<'articles'>[] = await getCollection('articles'); const sortedArticles = articles.sort( (a, b) => b.data.date.getTime() - a.data.date.getTime() ); // 获取所有标签 const allTags = articles.flatMap(article => article.data.tags || []); const tags = [...new Set(allTags)].sort(); // 获取内容结构 const { sections } = contentStructure; // 获取当前路径参数 const path = Astro.url.searchParams.get('path') || ''; const pathSegments = path ? decodeURIComponent(path).split('/') : []; // 获取标签参数 const tagFilter = Astro.url.searchParams.get('tag') || ''; // 获取视图模式参数 const viewMode = Astro.url.searchParams.get('view') || 'grid'; // 根据路径获取当前目录 function getCurrentSection(pathSegments: string[]) { // 过滤掉空字符串 const filteredSegments = pathSegments.filter(segment => segment.trim() !== ''); if (filteredSegments.length === 0) { return { sections, articles: contentStructure.articles, currentPath: '' }; } let currentSections = sections; let currentPath = ''; let currentArticles: string[] = []; // 遍历路径段,逐级查找 for (let i = 0; i < filteredSegments.length; i++) { const segment = filteredSegments[i]; // 查找当前段对应的目录 const foundSection = currentSections.find(s => s.name === segment); if (!foundSection) { return { sections: [], articles: [], currentPath: '' }; } // 更新当前路径 currentPath = currentPath ? `${currentPath}/${segment}` : segment; // 如果是最后一个段,返回该目录的内容 if (i === filteredSegments.length - 1) { return { sections: foundSection.sections, articles: foundSection.articles, currentPath }; } // 否则继续向下查找 currentSections = foundSection.sections; } // 默认返回空 return { sections: [], articles: [], currentPath: '' }; } // 获取当前目录内容 const { sections: currentSections, articles: currentArticles, currentPath } = getCurrentSection(pathSegments); // 如果有标签过滤,则过滤文章 let filteredArticles = sortedArticles; let pageTitle = currentPath ? currentPath : '文章列表'; if (tagFilter) { filteredArticles = sortedArticles.filter(article => article.data.tags && article.data.tags.includes(tagFilter) ); pageTitle = `标签: ${tagFilter}`; } // 获取面包屑导航 interface Breadcrumb { name: string; path: string; } ---
{viewMode === 'grid' ? ( <>
{/* 上一级目录卡片 - 仅在浏览目录时显示 */} {!tagFilter && pathSegments.length > 0 && ( 1 ? `?path=${encodeURIComponent(pathSegments.slice(0, -1).join('/'))}` : ''}`} class="group flex flex-col h-full p-4 border border-primary-100 dark:border-gray-700 rounded-xl bg-white dark:bg-gray-800 hover:shadow-xl transition-all duration-300 hover:border-primary-300 dark:hover:border-primary-600">
返回上级目录
返回上一级
)} {/* 目录卡片 - 仅在浏览目录时显示 */} {!tagFilter && currentSections.map(section => { // 确保目录链接正确生成 const dirLink = currentPath ? `${currentPath}/${section.name}` : section.name; return (
{section.name}
{section.sections.length > 0 && ( {section.sections.length} 个子目录 )} {section.articles.length > 0 && ( {section.articles.length} 篇文章 )}
); })} {/* 文章卡片 - 根据是否有标签过滤显示不同内容 */} {tagFilter ? ( // 显示标签过滤后的文章 filteredArticles.map(article => (

{article.data.title}

{article.data.summary && (

{article.data.summary}

)}
阅读全文
)) ) : ( // 显示当前目录的文章 currentArticles.map(articlePath => { // 获取文章ID const articleId = getRelativePath(articlePath); // 尝试不同的方式匹配文章 const article = articles.find(a => { // 1. 直接匹配完整路径 if (a.id === articleId) { return true; } // 2. 匹配文件名(不含路径和扩展名) const baseName = getBasename(articleId); if (a.id === baseName) { return true; } // 3. 尝试匹配相对路径的一部分 const articleParts = articleId.split('/'); const fileName = articleParts[articleParts.length - 1]; if (a.id.endsWith(fileName)) { return true; } // 4. 移除.md扩展名后匹配 const idWithoutExt = articleId.replace(/\.md$/, ''); if (a.id === idWithoutExt) { return true; } // 5. 处理多级目录结构 // 如果文章ID包含目录路径,尝试匹配最后的文件名部分 const articlePathParts = articlePath.split('/'); const articleFileName = articlePathParts[articlePathParts.length - 1]; const articleIdParts = a.id.split('/'); const articleIdFileName = articleIdParts[articleIdParts.length - 1]; if (articleFileName === articleIdFileName) { return true; } // 6. 移除扩展名后比较文件名 const fileNameWithoutExt = articleFileName.replace(/\.md$/, ''); if (articleIdFileName === fileNameWithoutExt) { return true; } return false; }); if (!article) { return (

文章不存在

ID: {articleId}

可用文章: {articles.map(a => a.id).join(', ')}
); } return (

{article.data.title}

{article.data.summary && (

{article.data.summary}

)}
阅读全文
); }) )}
{/* 空内容提示 */} {((tagFilter && filteredArticles.length === 0) || (!tagFilter && currentSections.length === 0 && currentArticles.length === 0)) && (

{tagFilter ? `没有找到标签为 "${tagFilter}" 的文章` : '此目录为空'}

{tagFilter ? '请尝试其他标签或返回文章列表' : '此目录下暂无内容,请浏览其他目录或返回上一级'}

)}

文章标签

{tags.map(tag => { const isActive = tag === tagFilter; return ( {tag} ); })}
) : ( )}