update: seo

This commit is contained in:
ctwj
2025-11-13 00:34:26 +08:00
parent 04b3838cea
commit c15132b45a
3 changed files with 31 additions and 26 deletions

View File

@@ -58,6 +58,7 @@ export const useGlobalSeo = () => {
return { return {
initSystemConfig, initSystemConfig,
systemConfig, systemConfig,
setPageSeo,
setHomeSeo, setHomeSeo,
setLoginSeo, setLoginSeo,
setRegisterSeo, setRegisterSeo,

View File

@@ -18,12 +18,12 @@ interface SystemConfig {
export const useSeo = () => { export const useSeo = () => {
const systemConfig = ref<SystemConfig | null>(null) const systemConfig = ref<SystemConfig | null>(null)
const { getSystemConfig } = useSystemConfigApi() const { getPublicSystemConfig } = usePublicSystemConfigApi()
// 获取系统配置 // 获取系统配置
const fetchSystemConfig = async () => { const fetchSystemConfig = async () => {
try { try {
const response = await getSystemConfig() as any const response = await getPublicSystemConfig() as any
console.log('系统配置响应:', response) console.log('系统配置响应:', response)
if (response && response.success && response.data) { if (response && response.success && response.data) {
systemConfig.value = response.data systemConfig.value = response.data
@@ -95,8 +95,8 @@ export const useSeo = () => {
} }
// 生成动态SEO元数据 // 生成动态SEO元数据
const generateDynamicSeo = (pageTitle: string, customMeta?: Record<string, string>, routeQuery?: Record<string, any>) => { const generateDynamicSeo = (pageTitle: string, customMeta?: Record<string, string>, routeQuery?: Record<string, any>, useRawTitle: boolean = false) => {
const title = generateTitle(pageTitle) const title = useRawTitle ? pageTitle : generateTitle(pageTitle)
const meta = generateMeta(customMeta) const meta = generateMeta(customMeta)
const route = routeQuery || useRoute() const route = routeQuery || useRoute()
@@ -129,6 +129,7 @@ export const useSeo = () => {
ogDescription: dynamicDescription, ogDescription: dynamicDescription,
ogType: 'website', ogType: 'website',
ogImage: ogImageUrl, ogImage: ogImageUrl,
ogSiteName: (systemConfig.value && systemConfig.value.site_title) || '老九网盘资源数据库',
twitterCard: 'summary_large_image', twitterCard: 'summary_large_image',
robots: 'index, follow' robots: 'index, follow'
} }
@@ -136,7 +137,9 @@ export const useSeo = () => {
// 设置页面SEO - 使用Nuxt3最佳实践 // 设置页面SEO - 使用Nuxt3最佳实践
const setPageSeo = (pageTitle: string, customMeta?: Record<string, string>, routeQuery?: Record<string, any>) => { const setPageSeo = (pageTitle: string, customMeta?: Record<string, string>, routeQuery?: Record<string, any>) => {
const seoData = generateDynamicSeo(pageTitle, customMeta, routeQuery) // 检测标题是否已包含站点名(以避免重复)
const isTitleFormatted = systemConfig.value && pageTitle.includes(systemConfig.value.site_title || '');
const seoData = generateDynamicSeo(pageTitle, customMeta, routeQuery, isTitleFormatted)
useSeoMeta({ useSeoMeta({
title: seoData.title, title: seoData.title,
@@ -146,6 +149,7 @@ export const useSeo = () => {
ogDescription: seoData.ogDescription, ogDescription: seoData.ogDescription,
ogType: seoData.ogType, ogType: seoData.ogType,
ogImage: seoData.ogImage, ogImage: seoData.ogImage,
ogSiteName: seoData.ogSiteName,
twitterCard: seoData.twitterCard, twitterCard: seoData.twitterCard,
robots: seoData.robots robots: seoData.robots
}) })

View File

@@ -1,5 +1,5 @@
<template> <template>
<div v-if="!systemConfig.maintenance_mode" class="min-h-screen bg-gray-50 dark:bg-slate-900 text-gray-800 dark:text-slate-100 flex flex-col"> <div v-if="!systemConfig?.maintenance_mode" class="min-h-screen bg-gray-50 dark:bg-slate-900 text-gray-800 dark:text-slate-100 flex flex-col">
<!-- 全局加载状态 --> <!-- 全局加载状态 -->
<div v-if="pageLoading" class="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50"> <div v-if="pageLoading" class="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50">
<div class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-xl"> <div class="bg-white dark:bg-gray-800 rounded-lg p-8 shadow-xl">
@@ -282,7 +282,7 @@
<!-- 悬浮按钮组件 --> <!-- 悬浮按钮组件 -->
<FloatButtons /> <FloatButtons />
</div> </div>
<div v-if="systemConfig.maintenance_mode" class="fixed inset-0 z-[1000000] flex items-center justify-center bg-gradient-to-br from-yellow-100/80 via-gray-900/90 to-yellow-200/80 backdrop-blur-sm"> <div v-if="systemConfig?.maintenance_mode" class="fixed inset-0 z-[1000000] flex items-center justify-center bg-gradient-to-br from-yellow-100/80 via-gray-900/90 to-yellow-200/80 backdrop-blur-sm">
<div class="bg-white dark:bg-gray-800 rounded-3xl shadow-2xl px-8 py-10 flex flex-col items-center max-w-xs w-full border border-yellow-200 dark:border-yellow-700"> <div class="bg-white dark:bg-gray-800 rounded-3xl shadow-2xl px-8 py-10 flex flex-col items-center max-w-xs w-full border border-yellow-200 dark:border-yellow-700">
<i class="fas fa-tools text-yellow-500 text-5xl mb-6 animate-bounce-slow"></i> <i class="fas fa-tools text-yellow-500 text-5xl mb-6 animate-bounce-slow"></i>
<h3 class="text-2xl font-extrabold text-yellow-600 dark:text-yellow-400 mb-2 tracking-wide drop-shadow">系统维护中</h3> <h3 class="text-2xl font-extrabold text-yellow-600 dark:text-yellow-400 mb-2 tracking-wide drop-shadow">系统维护中</h3>
@@ -311,7 +311,7 @@ const statsApi = useStatsApi()
const panApi = usePanApi() const panApi = usePanApi()
const publicSystemConfigApi = usePublicSystemConfigApi() const publicSystemConfigApi = usePublicSystemConfigApi()
// 获取路由参数 - 提前定义以避免初始化顺序问题 // 路由参数已通过自动导入提供,直接使用
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
@@ -332,10 +332,9 @@ const pageTitle = computed(() => {
const config = systemConfigData.value as any const config = systemConfigData.value as any
const siteTitle = (config?.data?.site_title) ? config.data.site_title : const siteTitle = (config?.data?.site_title) ? config.data.site_title :
(config?.site_title) ? config.site_title : '老九网盘资源数据库' (config?.site_title) ? config.site_title : '老九网盘资源数据库'
const searchKeyword = (route.query && route.query.search) ? route.query.search as string : '' const searchKeyword = (route.query?.search) ? route.query.search as string : ''
const platformId = (route.query && route.query.platform) ? route.query.platform as string : '' const platformId = (route.query?.platform) ? route.query.platform as string : ''
const platformName = getPlatformName(platformId) const platformName = getPlatformName(platformId)
let title = siteTitle let title = siteTitle
// 根据搜索条件组合标题 // 根据搜索条件组合标题
@@ -413,11 +412,12 @@ const pageKeywords = computed(() => {
}) })
// 设置页面SEO // 设置页面SEO
const { initSystemConfig, setHomeSeo, systemConfig } = useGlobalSeo() const { initSystemConfig, setPageSeo, systemConfig: seoSystemConfig } = useGlobalSeo()
// 更新页面SEO的函数 - 合并所有SEO设置到一个函数中 // 更新页面SEO的函数 - 合并所有SEO设置到一个函数中
const updatePageSeo = () => { const updatePageSeo = () => {
setHomeSeo({ // 使用动态计算的标题,而不是默认的"首页"
setPageSeo(pageTitle.value, {
description: pageDescription.value, description: pageDescription.value,
keywords: pageKeywords.value keywords: pageKeywords.value
}) })
@@ -426,8 +426,8 @@ const updatePageSeo = () => {
const config = useRuntimeConfig() const config = useRuntimeConfig()
const baseUrl = config.public.siteUrl || 'https://yourdomain.com' // 从环境变量获取 const baseUrl = config.public.siteUrl || 'https://yourdomain.com' // 从环境变量获取
const params = new URLSearchParams() const params = new URLSearchParams()
if (route.query.search) params.set('search', route.query.search as string) if (route.query?.search) params.set('search', route.query.search as string)
if (route.query.platform) params.set('platform', route.query.platform as string) if (route.query?.platform) params.set('platform', route.query.platform as string)
const queryString = params.toString() const queryString = params.toString()
const canonicalUrl = queryString ? `${baseUrl}?${queryString}` : baseUrl const canonicalUrl = queryString ? `${baseUrl}?${queryString}` : baseUrl
@@ -447,7 +447,7 @@ const updatePageSeo = () => {
innerHTML: JSON.stringify({ innerHTML: JSON.stringify({
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "WebSite", "@type": "WebSite",
"name": (systemConfig.value && systemConfig.value.site_title) || '老九网盘资源数据库', "name": (seoSystemConfig.value && seoSystemConfig.value.site_title) || '老九网盘资源数据库',
"description": pageDescription.value, "description": pageDescription.value,
"url": canonicalUrl "url": canonicalUrl
}) })
@@ -461,9 +461,9 @@ onBeforeMount(async () => {
updatePageSeo() updatePageSeo()
}) })
// 监听路由变化当搜索条件改变时更新SEO // 监听路由变化和系统配置数据,当搜索条件或配置改变时更新SEO
watch( watch(
() => [route.query.search, route.query.platform], () => [route.query?.search, route.query?.platform, systemConfigData.value],
() => { () => {
// 使用nextTick确保响应式数据已更新 // 使用nextTick确保响应式数据已更新
nextTick(() => { nextTick(() => {
@@ -520,10 +520,10 @@ const handleResourceImageError = (event: Event) => {
// 使用 useAsyncData 获取资源数据 // 使用 useAsyncData 获取资源数据
const { data: resourcesData, pending, refresh } = await useAsyncData( const { data: resourcesData, pending, refresh } = await useAsyncData(
() => `resources-1-${route.query.search || ''}-${route.query.platform || ''}`, () => `resources-1-${route.query?.search || ''}-${route.query?.platform || ''}`,
async () => { async () => {
// 如果有搜索关键词使用带搜索参数的资源接口后端会优先使用Meilisearch // 如果有搜索关键词使用带搜索参数的资源接口后端会优先使用Meilisearch
if (route.query.search) { if (route.query?.search) {
return await resourceApi.getResources({ return await resourceApi.getResources({
page: 1, page: 1,
page_size: 200, page_size: 200,
@@ -535,7 +535,7 @@ const { data: resourcesData, pending, refresh } = await useAsyncData(
return await resourceApi.getResources({ return await resourceApi.getResources({
page: 1, page: 1,
page_size: 200, page_size: 200,
pan_id: route.query.platform as string || '' pan_id: route.query?.platform as string || ''
}) })
} }
} }
@@ -620,8 +620,8 @@ const safeLoading = computed(() => pending.value)
// 从路由参数获取当前状态 // 从路由参数获取当前状态
const searchQuery = ref(route.query.search as string || '') const searchQuery = ref(route.query?.search as string || '')
const selectedPlatform = computed(() => route.query.platform as string || '') const selectedPlatform = computed(() => route.query?.platform as string || '')
// 记录搜索统计的函数 // 记录搜索统计的函数
const recordSearchStats = (keyword: string) => { const recordSearchStats = (keyword: string) => {
@@ -653,11 +653,11 @@ const handleSearch = () => {
onMounted(() => { onMounted(() => {
// 初始化认证状态 // 初始化认证状态
authInitialized.value = true authInitialized.value = true
animateCounters() animateCounters()
// 页面挂载完成时,如果有搜索关键词,记录搜索统计 // 页面挂载完成时,如果有搜索关键词,记录搜索统计
if (process.client && route.query.search) { if (process.client && route.query?.search) {
const searchKeyword = route.query.search as string const searchKeyword = route.query.search as string
recordSearchStats(searchKeyword) recordSearchStats(searchKeyword)
} else { } else {