feat(blog): add tagId and categoryId for multilingual routing support
- Add tagId and categoryId fields to blog post frontmatter and interfaces - Update blog list, category, and tag pages to use IDs for routing - Implement fallback to regular tags/categories when IDs are not available - Improve tag and category links with hover effects and proper encoding - Update post meta component to support multilingual routing
This commit is contained in:
@@ -48,14 +48,22 @@ export default function BlogList({ posts, lang, baseUrl = '/blog/posts/' }: Blog
|
||||
|
||||
{/* Tags */}
|
||||
<div className="flex flex-wrap gap-2 mb-4">
|
||||
{post.tags.map((tag, tagIndex) => (
|
||||
<span
|
||||
key={`${tag}-${tagIndex}`}
|
||||
className="px-2 py-1 text-xs bg-muted text-muted-foreground rounded-full"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
{post.tags.map((tag, tagIndex) => {
|
||||
// 使用 tagId 如果存在,否则使用 tag 本身
|
||||
const tagRoute = post.tagId && Array.isArray(post.tagId) && tagIndex < post.tagId.length
|
||||
? post.tagId[tagIndex]
|
||||
: tag.toLowerCase();
|
||||
|
||||
return (
|
||||
<a
|
||||
href={`/${lang === 'en' ? '' : 'zh/'}blog/tags/${encodeURIComponent(tagRoute)}`}
|
||||
key={`${tag}-${tagIndex}`}
|
||||
className="px-2 py-1 text-xs bg-muted text-muted-foreground rounded-full hover:bg-muted/80 transition-colors"
|
||||
>
|
||||
# {tag}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ export interface Props {
|
||||
publishDate?: string;
|
||||
readingTime?: number;
|
||||
tags?: string[];
|
||||
tagId?: string[];
|
||||
category?: string | string[];
|
||||
categoryId?: string[] | string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
@@ -16,7 +18,9 @@ const {
|
||||
publishDate,
|
||||
readingTime,
|
||||
tags,
|
||||
tagId,
|
||||
category,
|
||||
categoryId,
|
||||
className = ''
|
||||
} = Astro.props;
|
||||
|
||||
@@ -84,19 +88,26 @@ const getReadingTimeText = (minutes: number) => {
|
||||
{category && (
|
||||
<div class="space-y-2">
|
||||
<div class="text-xs font-medium text-muted-foreground uppercase tracking-wide">
|
||||
分类
|
||||
{lang === 'zh' ? '分类' : 'Categories'}
|
||||
</div>
|
||||
<div class="flex gap-2 flex-wrap">
|
||||
{Array.isArray(category) ? (
|
||||
category.map((cat) => (
|
||||
<span class="inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-gradient-to-r from-purple-500 to-purple-600 text-white shadow-sm hover:shadow-md transition-all duration-200 hover:scale-105">
|
||||
{cat}
|
||||
</span>
|
||||
))
|
||||
category.map((cat, index) => {
|
||||
// 获取对应的 categoryId,如果存在
|
||||
const catId = categoryId && Array.isArray(categoryId) && index < categoryId.length
|
||||
? categoryId[index]
|
||||
: cat.toLowerCase();
|
||||
|
||||
return (
|
||||
<a href={`/${lang === 'en' ? '' : 'zh/'}blog/categories/${encodeURIComponent(catId)}`} class="inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-gradient-to-r from-purple-500 to-purple-600 text-white shadow-sm hover:shadow-md transition-all duration-200 hover:scale-105">
|
||||
{cat}
|
||||
</a>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<span class="inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-gradient-to-r from-purple-500 to-purple-600 text-white shadow-sm hover:shadow-md transition-all duration-200 hover:scale-105">
|
||||
<a href={`/${lang === 'en' ? '' : 'zh/'}blog/categories/${encodeURIComponent(categoryId?.toString() || category.toLowerCase())}`} class="inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-gradient-to-r from-purple-500 to-purple-600 text-white shadow-sm hover:shadow-md transition-all duration-200 hover:scale-105">
|
||||
{category}
|
||||
</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -106,14 +117,21 @@ const getReadingTimeText = (minutes: number) => {
|
||||
{tags && tags.length > 0 && (
|
||||
<div class="space-y-2">
|
||||
<div class="text-xs font-medium text-muted-foreground uppercase tracking-wide">
|
||||
标签
|
||||
{lang === 'zh' ? '标签' : 'Tags'}
|
||||
</div>
|
||||
<div class="flex gap-2 flex-wrap">
|
||||
{tags.map((tag) => (
|
||||
<span class="inline-flex items-center px-2.5 py-1 rounded-md text-xs font-medium bg-gray-100 text-gray-700 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700 transition-colors border border-gray-200 dark:border-gray-600">
|
||||
# {tag}
|
||||
</span>
|
||||
))}
|
||||
{tags.map((tag, index) => {
|
||||
// 获取对应的 tagId,如果存在
|
||||
const tagRoute = tagId && Array.isArray(tagId) && index < tagId.length
|
||||
? tagId[index]
|
||||
: tag.toLowerCase();
|
||||
|
||||
return (
|
||||
<a href={`/${lang === 'en' ? '' : 'zh/'}blog/tags/${encodeURIComponent(tagRoute)}`} class="inline-flex items-center px-2.5 py-1 rounded-md text-xs font-medium bg-gray-100 text-gray-700 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700 transition-colors border border-gray-200 dark:border-gray-600">
|
||||
# {tag}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user