--- import { Icon } from "astro-icon/components"; import WidgetLayout from "@/components/common/WidgetLayout.astro"; import { siteConfig } from "@/config"; import I18nKey from "@/i18n/i18nKey"; import { i18n } from "@/i18n/translation"; import { getCategoryList, getSortedPosts, getTagList, } from "@/utils/content-utils"; interface Props { class?: string; style?: string; } const { class: className, style } = Astro.props; // 从配置中获取站点开始日期 const siteStartDate = siteConfig.siteStartDate || "2025-01-01"; // 获取所有文章 const posts = await getSortedPosts(); const categories = await getCategoryList(); const tags = await getTagList(); // 计算总字数 let totalWords = 0; for (const post of posts) { if (post.body) { // 移除代码块和内联代码后计算字数 let text = post.body .replace(/```[\s\S]*?```/g, "") // 移除代码块 .replace(/`[^`]*`/g, "") // 移除内联代码 .replace(/\s+/g, " ") // 合并空白 .trim(); // 分别计算中文字符和英文字符 const chineseChars = text.match(/[\u4e00-\u9fa5]/g) || []; const englishChars = text.match(/[a-zA-Z]/g) || []; totalWords += chineseChars.length + englishChars.length; } } // 格式化数字(添加千位分隔符) function formatNumber(num: number): string { return num.toLocaleString(); } // 获取最新文章日期(用于客户端计算) const latestPost = posts.reduce((latest, post) => { if (!latest) return post; return post.data.published > latest.data.published ? post : latest; }, posts[0]); const lastPostDate = latestPost ? latestPost.data.published.toISOString() : null; const todayText = i18n(I18nKey.today); const stats = [ { icon: "material-symbols:article-outline", label: i18n(I18nKey.siteStatsPostCount), value: posts.length, }, { icon: "material-symbols:folder-outline", label: i18n(I18nKey.siteStatsCategoryCount), value: categories.length, }, { icon: "material-symbols:label-outline", label: i18n(I18nKey.siteStatsTagCount), value: tags.length, }, { icon: "material-symbols:text-ad-outline-rounded", label: i18n(I18nKey.siteStatsTotalWords), value: totalWords, formatted: true, }, { icon: "material-symbols:calendar-clock-outline", label: i18n(I18nKey.siteStatsRunningDays), value: 0, // 将由客户端更新 suffix: i18n(I18nKey.siteStatsDays).replace("{days}", ""), dynamic: true, id: "running-days", }, { icon: "material-symbols:ecg-heart-outline", label: i18n(I18nKey.siteStatsLastUpdate), value: 0, // 将由客户端更新 suffix: i18n(I18nKey.siteStatsDaysAgo).replace("{days}", ""), dynamic: true, id: "last-update", }, ]; ---
{stats.map((stat) => (
{stat.label}
{stat.formatted ? formatNumber(stat.value) : stat.value} {stat.suffix && ( {stat.suffix} )}
))}