37 lines
1.4 KiB
TypeScript
37 lines
1.4 KiB
TypeScript
import type { PageSeo } from '~/types/site';
|
||
|
||
/**
|
||
* 页面 SEO 适配
|
||
*
|
||
* 从 dashboard 的 page-seo 配置读取 meta_title / meta_description / meta_keywords / og_image_url,
|
||
* 应用到当前页面的 useHead;未配置时回退到全局 SEO 默认值或页面默认标题。
|
||
*/
|
||
export async function usePageSeo(pageType: string, entityId?: number, fallbackTitle?: string) {
|
||
const { getPageSeo } = useSiteApi();
|
||
const siteStore = useSiteStore();
|
||
// 注意:本函数可能在 onMounted 等异步上下文中被调用,useI18n 要求 setup 顶层,
|
||
// 这里改用全局 i18n 实例($i18n.t 跟随当前 locale,任意上下文安全)
|
||
const i18n = (useNuxtApp() as unknown as { $i18n?: { t(key: string): string } }).$i18n;
|
||
const t = (key: string) => i18n?.t(key) || key;
|
||
|
||
let seo: PageSeo | null = null;
|
||
try {
|
||
seo = await getPageSeo(pageType, entityId);
|
||
} catch {
|
||
seo = null;
|
||
}
|
||
|
||
const title = seo?.meta_title || fallbackTitle || t('app.name');
|
||
const description = seo?.meta_description || siteStore.seo?.meta_description || '';
|
||
const keywords = seo?.meta_keywords || siteStore.seo?.meta_keywords || '';
|
||
|
||
useHead({
|
||
title,
|
||
meta: [
|
||
...(description ? [{ name: 'description', content: description }] : []),
|
||
...(keywords ? [{ name: 'keywords', content: keywords }] : []),
|
||
...(seo?.og_image_url ? [{ property: 'og:image', content: seo.og_image_url }] : [])
|
||
]
|
||
});
|
||
}
|