chore: checkpoint ai search comments and i18n foundation

This commit is contained in:
2026-03-28 17:17:31 +08:00
parent d18a709987
commit ec96d91548
71 changed files with 9494 additions and 423 deletions

View File

@@ -10,6 +10,7 @@ import StatsList from '../components/StatsList.astro';
import TechStackList from '../components/TechStackList.astro';
import { terminalConfig } from '../lib/config/terminal';
import { api, DEFAULT_SITE_SETTINGS } from '../lib/api/client';
import { formatReadTime, getI18n } from '../lib/i18n';
import type { AppFriendLink } from '../lib/api/client';
import type { Post } from '../lib/types';
@@ -26,6 +27,7 @@ let tags: string[] = [];
let friendLinks: AppFriendLink[] = [];
let categories: Awaited<ReturnType<typeof api.getCategories>> = [];
let apiError: string | null = null;
const { locale, t } = getI18n(Astro);
try {
siteSettings = await api.getSiteSettings();
@@ -40,23 +42,32 @@ try {
friendLinks = (await api.getFriendLinks()).filter(friend => friend.status === 'approved');
categories = await api.getCategories();
} catch (error) {
apiError = error instanceof Error ? error.message : 'API unavailable';
apiError = error instanceof Error ? error.message : t('common.apiUnavailable');
console.error('API Error:', error);
}
const systemStats = [
{ label: '文章', value: String(allPosts.length) },
{ label: '标签', value: String(tags.length) },
{ label: '分类', value: String(categories.length) },
{ label: '友链', value: String(friendLinks.length) },
{ label: t('common.posts'), value: String(allPosts.length) },
{ label: t('common.tags'), value: String(tags.length) },
{ label: t('common.categories'), value: String(categories.length) },
{ label: t('common.friends'), value: String(friendLinks.length) },
];
const techStack = siteSettings.techStack.map(name => ({ name }));
const postTypeFilters = [
{ id: 'all', name: '全部', icon: 'fa-stream' },
{ id: 'article', name: terminalConfig.postTypes.article.label, icon: 'fa-file-alt' },
{ id: 'tweet', name: terminalConfig.postTypes.tweet.label, icon: 'fa-comment-dots' }
{ id: 'all', name: t('common.all'), icon: 'fa-stream' },
{ id: 'article', name: t('common.article'), icon: 'fa-file-alt' },
{ id: 'tweet', name: t('common.tweet'), icon: 'fa-comment-dots' }
];
const navLinks = [
{ icon: 'fa-file-code', text: t('nav.articles'), href: '/articles' },
{ icon: 'fa-folder', text: t('nav.categories'), href: '/categories' },
{ icon: 'fa-tags', text: t('nav.tags'), href: '/tags' },
{ icon: 'fa-stream', text: t('nav.timeline'), href: '/timeline' },
{ icon: 'fa-star', text: t('nav.reviews'), href: '/reviews' },
{ icon: 'fa-link', text: t('nav.friends'), href: '/friends' },
{ icon: 'fa-user-secret', text: t('nav.about'), href: '/about' },
];
---
@@ -78,7 +89,7 @@ const postTypeFilters = [
<div class="mb-8 px-4">
<CommandPrompt command="ls -l" />
<div class="ml-4 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-6 gap-4">
{terminalConfig.navLinks.map(link => (
{navLinks.map(link => (
<a
href={link.href}
class="flex items-center gap-2 text-[var(--text)] hover:text-[var(--primary)] transition-colors py-2"
@@ -126,17 +137,22 @@ const postTypeFilters = [
<div class="mb-8 px-4">
<CommandPrompt command="cat ./pinned_post.md" />
<div class="ml-4">
<div
class="p-4 rounded-lg border border-[var(--border-color)] bg-[var(--header-bg)] cursor-pointer hover:border-[var(--primary)] transition-colors"
onclick={`window.location.href='/articles/${pinnedPost.slug}'`}
>
<div class="p-4 rounded-lg border border-[var(--border-color)] bg-[var(--header-bg)] transition-colors hover:border-[var(--primary)]">
<div class="flex items-center gap-2 mb-2">
<span class="px-2 py-0.5 text-xs rounded bg-[var(--primary)] text-[var(--terminal-bg)] font-bold">置顶</span>
<span class="px-2 py-0.5 text-xs rounded bg-[var(--primary)] text-[var(--terminal-bg)] font-bold">{t('home.pinned')}</span>
<span class="w-3 h-3 rounded-full" style={`background-color: ${pinnedPost.type === 'article' ? 'var(--primary)' : 'var(--secondary)'}`}></span>
<h3 class="text-lg font-bold">{pinnedPost.title}</h3>
<a href={`/articles/${pinnedPost.slug}`} class="text-lg font-bold text-[var(--title-color)] transition hover:text-[var(--primary)]">
{pinnedPost.title}
</a>
</div>
<p class="text-sm text-[var(--text-secondary)] mb-2">{pinnedPost.date} | 阅读时间: {pinnedPost.readTime}</p>
<p class="text-sm text-[var(--text-secondary)] mb-2">{pinnedPost.date} | {t('common.readTime')}: {formatReadTime(locale, pinnedPost.readTime, t)}</p>
<p class="text-[var(--text-secondary)]">{pinnedPost.description}</p>
<div class="mt-4">
<a href={`/articles/${pinnedPost.slug}`} class="terminal-action-button inline-flex">
<i class="fas fa-angle-right"></i>
<span>{t('common.readMore')}</span>
</a>
</div>
</div>
</div>
</div>
@@ -151,7 +167,7 @@ const postTypeFilters = [
))}
</div>
<div class="mt-4">
<ViewMoreLink href="/articles" text="查看所有文章" />
<ViewMoreLink href="/articles" text={t('common.viewAllArticles')} />
</div>
</div>
</div>
@@ -178,7 +194,7 @@ const postTypeFilters = [
))}
</div>
<div class="mt-6 ml-4">
<ViewMoreLink href="/friends" text="查看全部友链" />
<ViewMoreLink href="/friends" text={t('common.viewAllLinks')} />
</div>
</div>
@@ -189,15 +205,15 @@ const postTypeFilters = [
<div class="ml-4">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">关于我</h3>
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">{t('home.about')}</h3>
<p class="text-[var(--text-secondary)] mb-4">{siteSettings.ownerBio}</p>
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">技术栈</h3>
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">{t('home.techStack')}</h3>
<TechStackList items={techStack} />
</div>
<div>
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">系统状态</h3>
<h3 class="text-lg font-bold mb-3 text-[var(--title-color)]">{t('home.systemStatus')}</h3>
<StatsList stats={systemStats} />
</div>
</div>