From 6c3cdc24707c16851ad2a13feb5477a350410118 Mon Sep 17 00:00:00 2001 From: doget Date: Thu, 4 Sep 2025 19:06:49 +0800 Subject: [PATCH] =?UTF-8?q?=E8=83=BD=E6=A3=80=E7=B4=A2=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/blog/[...slug].vue | 13 ++++++----- pages/blog/index.vue | 26 +++++++++++++++------- pages/contact.vue | 9 +++++++- pages/index.vue | 48 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/pages/blog/[...slug].vue b/pages/blog/[...slug].vue index 454f5fb..cb3f5e2 100644 --- a/pages/blog/[...slug].vue +++ b/pages/blog/[...slug].vue @@ -118,7 +118,9 @@ const currentLocale = ref(locale.value) // Get the slug from the route const slug = route.params.slug -const articlePath = `/${Array.isArray(slug) ? slug.join('/') : slug}` +const base = `/${Array.isArray(slug) ? slug.join('/') : slug}` +// Our list links to /blog/{locale}/{slug}, remove /blog prefix to query content file +const articlePath = base.replace(/^\/blog(?=\/)/, '') // Fetch the article const { data: article, pending, error } = await useAsyncData(`article-${articlePath}`, async () => { @@ -140,9 +142,7 @@ useSeoMeta({ twitterCard: 'summary_large_image' }) -const availableLocales = computed(() => - locales.value.filter(locale => locale.code !== 'en' || locale.code === currentLocale.value) -) +const availableLocales = computed(() => locales.value) const formatDate = (date) => { return new Date(date).toLocaleDateString('en-US', { @@ -156,9 +156,10 @@ const switchToTranslation = async (targetLocale) => { if (targetLocale === currentLocale.value) return try { - const translated = await queryContent(`/${targetLocale}${articlePath}`).findOne() + const base = articlePath.replace(/^\/(en|zh|zh-hant)/,'') + const translated = await queryContent(`/${targetLocale}${base}`).findOne() if (translated?._path) { - await navigateTo(translated._path) + await navigateTo(`/blog${translated._path}`) return } throw new Error('Not found') diff --git a/pages/blog/index.vue b/pages/blog/index.vue index 3b4586d..ef5e5ce 100644 --- a/pages/blog/index.vue +++ b/pages/blog/index.vue @@ -47,7 +47,7 @@

- + {{ article.title }}

@@ -58,7 +58,7 @@
{{ $t('blog.readMore') }} @@ -107,11 +107,11 @@ useSeoMeta({ const { locales } = useI18n() const currentLocale = ref(locale.value) -// Fetch blog articles -const { data: articles, pending, error } = await useAsyncData('blog-articles', async () => { +// Fetch blog articles (filter by current _locale provided by @nuxt/content) +const { data: articles, pending, error } = await useAsyncData(() => `blog-${locale.value}`, async () => { try { - return await queryContent(`/${locale.value}`) - .where({ _type: 'markdown' }) + return await queryContent() + .where({ _locale: locale.value }) .sort({ date: -1 }) .find() } catch (err) { @@ -119,6 +119,15 @@ const { data: articles, pending, error } = await useAsyncData('blog-articles', a return [] } }) +// Build localized link for article +const articleLink = (a) => { + if (!a || !a._path) return '/blog' + const hasLocale = /^\/(en|zh|zh-hant)(\/|$)/.test(a._path) + const localized = hasLocale + ? a._path + : (locale.value === 'en' ? a._path : `/${locale.value}${a._path}`) + return `/blog${localized}` +} const availableLocales = computed(() => locales.value.filter(locale => locale.code !== 'en' || locale.code === currentLocale.value) @@ -136,9 +145,10 @@ const switchToTranslation = async (article, targetLocale) => { if (targetLocale === currentLocale.value) return try { - const translated = await queryContent(`/${targetLocale}${article._path}`).findOne() + const basePath = article._path.replace(/^\/(en|zh|zh-hant)/, '') + const translated = await queryContent(`/${targetLocale}${basePath}`).findOne() if (translated?._path) { - await navigateTo(translated._path) + await navigateTo(`/blog${translated._path}`) return } throw new Error('Not found') diff --git a/pages/contact.vue b/pages/contact.vue index 3b5ce46..67158bf 100644 --- a/pages/contact.vue +++ b/pages/contact.vue @@ -209,11 +209,18 @@ const submitForm = async () => { throw new Error('invalid_email') } const fd = new FormData() + // 更友好的字段标签(供邮件展示) + fd.append('🧑 姓名', form.value.name) + fd.append('✉️ 邮箱', form.value.email) + fd.append('🧩 主题', form.value.subject) + fd.append('💬 消息', form.value.message) + // 兼容性保留原始字段(便于自动解析和统计) fd.append('name', form.value.name) fd.append('email', form.value.email) fd.append('subject', form.value.subject) fd.append('message', form.value.message) - fd.append('_subject', `Website Contact: ${form.value.subject}`) + // 自定义邮件主题/语言/回复地址 + fd.append('_subject', `📨 ${t('contact.title')} | ${form.value.subject}`) fd.append('_language', locale.value) fd.append('_replyto', form.value.email) diff --git a/pages/index.vue b/pages/index.vue index fa651df..1da2513 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -46,6 +46,33 @@
+ +
+
+
+

最新文章

+

为你精选的最新内容

+
+ +
加载中...
+ +
+ +
+

{{ a.title || 'Untitled' }}

+
+

{{ a.description || '' }}

+
{{ a.date ? new Date(a.date).toLocaleDateString() : '' }}
+
+
+
+
+
@@ -129,6 +156,27 @@ useSeoMeta({ description: () => t('seo.home.description') }) +// Latest articles (from @nuxt/content) filtered by _locale +const { data: articles, pending } = await useAsyncData(() => `home-articles-${locale.value}`, + async () => { + try { + return await queryContent() + .where({ _locale: locale.value }) + .sort({ date: -1 }) + .limit(3) + .find() + } catch (err) { + console.error('Error fetching home articles:', err) + return [] + } + } +) + +const articleLink = (a) => { + if (!a || !a._path) return '/blog' + return `/blog${a._path}` +} + // Services data const services = computed(() => [ {