feat: 为各个页面补全标题与SEO
All checks were successful
deploy to server / build-and-deploy (push) Successful in 3m4s

This commit is contained in:
2025-11-07 15:37:18 +08:00
parent 1cdc29b1ce
commit 0265ea4978
16 changed files with 150 additions and 10 deletions

View File

@ -0,0 +1,47 @@
/**
* 设置页面级 SEO 元数据(包含 title、description、OG/Twitter 等常用字段)。
*
* 该函数基于 `useSeoMeta` 封装,可用于 Nuxt 3 / Nuxt 4
* 配合 SSR/CSR 动态更新,可安全用于异步数据场景(如 CMS 内容页)。
*
* @param {Object} meta - 页面 SEO 配置对象
* @param {string} meta.title - 页面标题(会同时应用到 title / og:title
* @param {string} [meta.description] - 页面描述(会应用到 description / og:description
* @param {string} [meta.image] - 用于分享卡片的预览图og:image / twitter:image
*
* @example
* // 用于普通页面
* usePageSeo({
* title: '产品中心 - 金申机械',
* description: '查看全系列纸管机械产品',
* image: '/images/og/products.png'
* })
*
* @example
* // 用于动态内容(如产品详情页)
* const product = await fetchProduct()
* usePageSeo({
* title: product.name,
* description: product.summary,
* image: product.coverImage
* })
*
* @remarks
* - 自动生成以下 meta`title`, `description`, `og:title`, `og:description`, `og:image`, `twitter:card`
* - 默认使用 `summary_large_image` 作为 Twitter 卡片类型
* - 推荐与 `useHead()` 配合增加 canonical / alternate hreflang 等额外 SEO 标签
*/
export function usePageSeo(meta: {
title: string;
description?: string;
image?: string;
}) {
useSeoMeta({
title: meta.title,
ogTitle: meta.title,
description: meta.description,
ogDescription: meta.description,
ogImage: meta.image,
twitterCard: 'summary_large_image',
});
}

View File

@ -12,6 +12,17 @@
</el-container>
</template>
<script setup lang="ts">
const { t } = useI18n();
useHead(() => {
const siteTitle = t('company-name');
return {
titleTemplate: (title) => (title ? `${title} - ${siteTitle}` : siteTitle),
};
});
</script>
<style scoped>
.app-container {
display: flex;

View File

@ -3,3 +3,14 @@
<slot />
</div>
</template>
<script setup lang="ts">
const { t } = useI18n();
useHead(() => {
const siteTitle = `${$t('page-title.preview')} - ${t('company-name')}`;
return {
title: siteTitle,
};
});
</script>

View File

@ -38,6 +38,11 @@
statusMessage: '文件未找到',
});
}
const pageTitle = $t('page-title.download');
usePageSeo({
title: file.value.filename_download || pageTitle,
});
</script>
<style scoped>

View File

@ -19,9 +19,16 @@
return toHomepageView(data.value);
});
const pageTilte = $t('page-title.homepage');
watch(error, (value) => {
if (value) {
console.error('数据获取失败: ', value);
}
});
useSeoMeta({
title: pageTilte,
description: $t('company-description'),
});
</script>

View File

@ -60,14 +60,9 @@
});
// SEO
useHead({
title: computed(() => product.value?.name || 'Product Detail'),
meta: [
{
name: 'description',
content: computed(() => product.value?.summary || ''),
},
],
usePageSeo({
title: product.value.name || $t('page-title.products'),
description: product.value.summary || '',
});
</script>

View File

@ -102,6 +102,11 @@
];
}
});
const pageTitle = $t('page-title.products');
usePageSeo({
title: pageTitle,
});
</script>
<style scoped>

View File

@ -49,6 +49,11 @@
console.error('数据获取失败: ', value);
}
});
usePageSeo({
title: solution.value.title || $t('page-title.solutions'),
description: solution.value.summary || '',
});
</script>
<style scoped>

View File

@ -86,6 +86,11 @@
console.error('数据获取失败: ', value);
}
});
const pageTitle = $t('page-title.solutions');
usePageSeo({
title: pageTitle,
});
</script>
<style scoped>

View File

@ -31,6 +31,11 @@
console.error('数据获取失败: ', value);
}
});
const pageTitle = $t('page-title.contact-us');
usePageSeo({
title: pageTitle,
});
</script>
<style scoped>

View File

@ -111,6 +111,11 @@
console.error('数据获取失败: ', value);
}
});
const pageTitle = $t('page-title.documents');
usePageSeo({
title: pageTitle,
});
</script>
<style scoped>

View File

@ -112,6 +112,11 @@
console.error('数据获取失败: ', value);
}
});
const pageTitle = $t('page-title.faq');
usePageSeo({
title: pageTitle,
});
</script>
<style scoped>

View File

@ -52,6 +52,11 @@
iconComponent: ElIconService,
},
];
const pageTitle = $t('page-title.support');
usePageSeo({
title: pageTitle,
});
</script>
<style scoped>