feat(app): 添加多模板关于我们页面及相关路由和404页面
- 新增404页面,优化未找到页面体验,避免被搜索引擎索引 - 增加文件代理接口,隐藏真实文件服务器地址,支持文件请求代理 - 实现/article、/case、/product及/page动态路由兼容列表与详情展示 - 添加动态CMS页面兼容入口处理旧式路径,统一路由与SEO设置 - 新增模板1、模板7、模板2、模板3关于我们页面,实现多模板支持 - 模板增强支持CMS单页内容加载及SEO信息动态设置 - 配置环境变量及Git忽略文件规则辅助开发和构建环境管理
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import { useHead, useRequestURL, useSeoMeta, useRuntimeConfig } from '#app'
|
||||
import type { CmsSiteInfo } from '~/types'
|
||||
|
||||
type SeoInput = {
|
||||
title: string
|
||||
description?: string
|
||||
keywords?: string
|
||||
path?: string
|
||||
image?: string
|
||||
type?: 'website' | 'article' | 'product'
|
||||
siteName?: string
|
||||
publishedTime?: string
|
||||
modifiedTime?: string
|
||||
}
|
||||
|
||||
function getSiteOrigin() {
|
||||
if (import.meta.client) return window.location.origin
|
||||
try {
|
||||
return useRequestURL().origin
|
||||
} catch {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面 SEO 设置
|
||||
* 设置 TDK、Open Graph、Twitter Card、Canonical URL
|
||||
*/
|
||||
export function usePageSeo(input: SeoInput, site?: CmsSiteInfo | null) {
|
||||
const origin = getSiteOrigin()
|
||||
const url = input.path && origin ? new URL(input.path, origin).toString() : undefined
|
||||
const overrideSiteName = (useRuntimeConfig().public.siteName as string) || ''
|
||||
const siteName = input.siteName || overrideSiteName || site?.websiteName || ''
|
||||
const description = input.description || site?.comments || site?.content || ''
|
||||
const keywords = input.keywords || site?.keywords || ''
|
||||
const image = input.image || site?.websiteLogo || ''
|
||||
|
||||
const fullTitle = siteName ? `${input.title} - ${siteName}` : input.title
|
||||
|
||||
useSeoMeta({
|
||||
title: fullTitle,
|
||||
description,
|
||||
keywords,
|
||||
ogTitle: input.title,
|
||||
ogDescription: description,
|
||||
ogType: input.type || 'website',
|
||||
ogSiteName: siteName,
|
||||
...(image ? { ogImage: image } : {}),
|
||||
...(url ? { ogUrl: url } : {}),
|
||||
twitterCard: 'summary_large_image',
|
||||
twitterTitle: input.title,
|
||||
twitterDescription: description,
|
||||
...(image ? { twitterImage: image } : {}),
|
||||
...(input.publishedTime ? { articlePublishedTime: input.publishedTime } : {}),
|
||||
...(input.modifiedTime ? { articleModifiedTime: input.modifiedTime } : {})
|
||||
})
|
||||
|
||||
if (url) {
|
||||
useHead({
|
||||
link: [{ rel: 'canonical', href: url }]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入 JSON-LD 结构化数据
|
||||
*/
|
||||
export function useJsonLd(data: Record<string, unknown> | Record<string, unknown>[]) {
|
||||
const items = Array.isArray(data) ? data : [data]
|
||||
|
||||
useHead({
|
||||
script: items.map((item) => ({
|
||||
type: 'application/ld+json',
|
||||
innerHTML: JSON.stringify(item)
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入企业组织结构化数据
|
||||
*/
|
||||
export function useOrganizationSeo(site?: CmsSiteInfo | null) {
|
||||
if (!site) return
|
||||
|
||||
const origin = getSiteOrigin()
|
||||
const rawPhone = site.phone || ''
|
||||
const phone = rawPhone && !rawPhone.includes('*')
|
||||
? rawPhone
|
||||
: (useRuntimeConfig().public.phone as string) || site.config?.tel || rawPhone || ''
|
||||
const email = site.config?.email || site.email || ''
|
||||
const address = site.address || site.config?.address || ''
|
||||
const logo = site.websiteLogo || ''
|
||||
const overrideSiteName = (useRuntimeConfig().public.siteName as string) || ''
|
||||
|
||||
useJsonLd({
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Organization',
|
||||
name: overrideSiteName || site.websiteName || '',
|
||||
url: origin,
|
||||
...(logo ? { logo: new URL(logo, origin).toString() } : {}),
|
||||
...(phone ? { telephone: phone } : {}),
|
||||
...(email ? { email: email } : {}),
|
||||
...(address ? { address: { '@type': 'PostalAddress', address } } : {})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入面包屑结构化数据
|
||||
*/
|
||||
export function useBreadcrumbSeo(items: { name: string; url: string }[]) {
|
||||
const origin = getSiteOrigin()
|
||||
|
||||
useJsonLd({
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'BreadcrumbList',
|
||||
itemListElement: items.map((item, index) => ({
|
||||
'@type': 'ListItem',
|
||||
position: index + 1,
|
||||
name: item.name,
|
||||
item: new URL(item.url, origin).toString()
|
||||
}))
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user