From 2d4eeb362c885ffc2dc2b369efc103b9ca8787e5 Mon Sep 17 00:00:00 2001 From: biss Date: Fri, 19 Jun 2026 08:55:14 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BD=91=E7=AB=99=E4=BF=A1=E6=81=AF=E5=8D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- site.config.mjs | 12 +- src/components/ArticleSidebar.astro | 6 +- src/components/HomeSidebar.astro | 3 + src/components/SiteInfoCard.astro | 88 ++++++++++ src/layouts/BaseLayout.astro | 1 + src/pages/posts/[slug].astro | 2 +- src/styles/site.css | 55 +++++++ workers/umami-site-stats.js | 155 ++++++++++++++++++ .../umami-site-stats.wrangler.example.toml | 12 ++ 9 files changed, 329 insertions(+), 5 deletions(-) create mode 100644 src/components/SiteInfoCard.astro create mode 100644 workers/umami-site-stats.js create mode 100644 workers/umami-site-stats.wrangler.example.toml diff --git a/site.config.mjs b/site.config.mjs index beed379..2be02d6 100644 --- a/site.config.mjs +++ b/site.config.mjs @@ -35,7 +35,7 @@ export const siteConfig = { { label: '隐私政策', href: '/privacy/' }, ], poweredBy: [ - { label: 'EdgeOne', href: 'https://edgeone.ai/' }, + { label: 'Fastly', href: 'https://fastly.com/' }, { label: 'ASTRO', href: 'https://astro.build/' }, ], }, @@ -52,14 +52,19 @@ export const siteConfig = { region: '', script: 'https://cdn.jsdelivr.net/npm/twikoo@1.7.7/dist/twikoo.min.js', }, + analytics: { + umami: { + script: 'https://umami.biss.click/script.js', + websiteId: '3d97b310-b241-4fc6-bc9c-68e317fc7d42', + statsEndpoint: 'https://blogumami.biss.click', + }, + }, externalLinks: { waitSeconds: 10, whitelist: [ 'blog.biss.click', 'biss.click', 'github.com', - 'astro.build', - 'edgeone.ai', 'localhost', '127.0.0.1', ], @@ -121,6 +126,7 @@ export const publicSiteConfig = { site: siteConfig.site, author: siteConfig.author, comments: siteConfig.comments, + analytics: siteConfig.analytics, talks: siteConfig.talks, search: siteConfig.search, externalLinks: siteConfig.externalLinks, diff --git a/src/components/ArticleSidebar.astro b/src/components/ArticleSidebar.astro index 7d651d0..8e2885c 100644 --- a/src/components/ArticleSidebar.astro +++ b/src/components/ArticleSidebar.astro @@ -1,5 +1,6 @@ --- import { getCategoryHref, type BlogPost } from '@/lib/posts'; +import SiteInfoCard from '@/components/SiteInfoCard.astro'; import { siteConfig } from '../../site.config.mjs'; type TocItem = { @@ -17,9 +18,10 @@ interface Props { post: BlogPost; toc: TocItem[]; relatedPosts: BlogPost[]; + posts: BlogPost[]; } -const { post, toc, relatedPosts } = Astro.props; +const { post, toc, relatedPosts, posts } = Astro.props; const avatar = siteConfig.author.avatar; const topDepth = toc.length > 0 ? Math.min(...toc.map((item) => item.depth)) : 1; const tocSections = toc.reduce((sections, item) => { @@ -107,5 +109,7 @@ const tocSections = toc.reduce((sections, item) => { )} + + diff --git a/src/components/HomeSidebar.astro b/src/components/HomeSidebar.astro index d4d9991..6aae57f 100644 --- a/src/components/HomeSidebar.astro +++ b/src/components/HomeSidebar.astro @@ -1,5 +1,6 @@ --- import type { BlogPost } from '@/lib/posts'; +import SiteInfoCard from '@/components/SiteInfoCard.astro'; import { siteConfig } from '../../site.config.mjs'; interface Props { @@ -111,6 +112,8 @@ const recentPosts = posts.slice(0, 5); ))} + + diff --git a/src/components/SiteInfoCard.astro b/src/components/SiteInfoCard.astro new file mode 100644 index 0000000..01ac38c --- /dev/null +++ b/src/components/SiteInfoCard.astro @@ -0,0 +1,88 @@ +--- +import type { BlogPost } from '@/lib/posts'; +import { siteConfig } from '../../site.config.mjs'; + +interface Props { + posts: BlogPost[]; +} + +const { posts } = Astro.props; +const latestPost = posts[0]; +const totalWordCount = posts.reduce((total, post) => { + const plainText = post.body + .replace(/```[\s\S]*?```/g, '') + .replace(/<[^>]+>/g, '') + .replace(/[#>*_`~\-\[\]\(\)]/g, '') + .replace(/\s+/g, ''); + + return total + plainText.length; +}, 0); +const formatStatNumber = (value: number) => new Intl.NumberFormat('en-US').format(value); +const siteStats = [ + { label: '文章数目', value: formatStatNumber(posts.length) }, + { label: '本站总字数', value: formatStatNumber(totalWordCount) }, + { label: '本站访客数', value: '--', key: 'visitors' }, + { label: '本站访问量', value: '--', key: 'pageviews' }, + { label: '最后更新时间', value: latestPost?.dateText ?? '--' }, +]; +const statsEndpoint = siteConfig.analytics.umami.statsEndpoint; +--- + + + + diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 9a0240e..3bede78 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -21,6 +21,7 @@ const publicConfigJson = JSON.stringify(publicSiteConfig).replace(/ +