2b69686795
- 新增404页面,优化未找到页面体验,避免被搜索引擎索引 - 增加文件代理接口,隐藏真实文件服务器地址,支持文件请求代理 - 实现/article、/case、/product及/page动态路由兼容列表与详情展示 - 添加动态CMS页面兼容入口处理旧式路径,统一路由与SEO设置 - 新增模板1、模板7、模板2、模板3关于我们页面,实现多模板支持 - 模板增强支持CMS单页内容加载及SEO信息动态设置 - 配置环境变量及Git忽略文件规则辅助开发和构建环境管理
93 lines
3.1 KiB
Vue
93 lines
3.1 KiB
Vue
<template>
|
|
<div>
|
|
<Component :is="templatePage" v-if="templatePage" />
|
|
<SiteLoading v-else />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
/**
|
|
* CMS 页面路由
|
|
* /page/:id → 既支持旧的导航节点 ID(数字),也支持新版「单页管理」的 path(slug)
|
|
* 数字 id → 按 navigationId 取 cms_navigation + cms_design 内容
|
|
* 非数字 slug → 按 path 取 cms_page 已发布单页(website-admin「单页管理」模块)
|
|
*/
|
|
const route = useRoute()
|
|
const id = route.params.id as string
|
|
const isNumeric = /^\d+$/.test(id)
|
|
const slug = isNumeric ? undefined : id
|
|
|
|
// 规范路由收敛:单页的规范地址是顶层 /about、/contact(独立富组件),
|
|
// /page/about、/page/contact 仅作兼容入口,统一 301 到规范地址,避免重复页与 SEO 分散。
|
|
const CANONICAL_PAGE_ROUTE: Record<string, string> = { about: '/about', contact: '/contact' }
|
|
if (slug && CANONICAL_PAGE_ROUTE[slug]) {
|
|
// 规范地址收敛:用 Nuxt 标准的 navigateTo 301 重定向(createError 仅渲染错误页,不会真正跳转)
|
|
throw navigateTo(CANONICAL_PAGE_ROUTE[slug], { redirectCode: 301 })
|
|
}
|
|
|
|
const { loadTemplate } = useTemplate()
|
|
const { siteInfo, navigations, fetchSiteInfo } = useSite()
|
|
|
|
await fetchSiteInfo()
|
|
|
|
const templatePage = shallowRef<Component | null>(null)
|
|
const components = await loadTemplate()
|
|
// 语义化 slug 优先映射到独立页面组件(about→关于我们、contact→联系我们),
|
|
// 避免有专属组件的 slug 落入通用单页 Page 逻辑——CMS 未录入正文时会显示空状态。
|
|
// (这些页面已有结构化组件,内容更丰富,无需依赖 CMS 单页正文。)
|
|
const standaloneComp =
|
|
slug === 'about' ? components?.About
|
|
: slug === 'contact' ? components?.Contact
|
|
: null
|
|
templatePage.value = standaloneComp || components?.Page || null
|
|
|
|
// 从导航中查找当前页面信息(仅数字 id 时有效)
|
|
const currentNav = computed(() => {
|
|
if (isNumeric) {
|
|
const navs = navigations.value || []
|
|
const findNav = (items: any[]): any => {
|
|
for (const item of items) {
|
|
if (String(item.navigationId) === id) return item
|
|
if (item.children?.length) {
|
|
const found = findNav(item.children)
|
|
if (found) return found
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
return findNav(navs)
|
|
}
|
|
return undefined
|
|
})
|
|
|
|
// 非数字 slug:拉取单页 SEO 信息(标题/关键词/描述/头图)
|
|
let seoData = ref<{
|
|
title?: string
|
|
keywords?: string
|
|
description?: string
|
|
photo?: string | null
|
|
} | null>(null)
|
|
if (!isNumeric && slug) {
|
|
const { data } = await useFetch<{
|
|
title?: string
|
|
keywords?: string
|
|
description?: string
|
|
photo?: string | null
|
|
}>('/api/page/detail', {
|
|
query: { path: slug }
|
|
})
|
|
seoData = data
|
|
}
|
|
|
|
usePageSeo(
|
|
{
|
|
title: seoData.value?.title || currentNav.value?.title || (slug === 'about' ? '关于我们' : slug === 'contact' ? '联系我们' : '页面'),
|
|
path: route.fullPath,
|
|
keywords: seoData.value?.keywords,
|
|
description: seoData.value?.description,
|
|
image: seoData.value?.photo || undefined
|
|
},
|
|
siteInfo.value
|
|
)
|
|
</script>
|