Skip to content
0

给Teek配置go壁纸api

date: 2025-09-25 18:07:27 title: 给Teek配置go壁纸api categories:


给Teek配置go壁纸api

image-20250925184754837

目录

[toc]

需求

📌需求:给宇宙最美博客-Teek 接入一个壁纸api

📌具体描述:

目前,宇宙最美博客-Teek的壁纸 已具备 每隔8s随机从壁纸库 显示一张新壁纸功能了,且壁纸有动态放大缩小效果,很美观👏。

此时,我想实现一个 壁纸api 的需求:

我们对用户只需要暴漏一个域名地址,例如imgapi.onedayxyy.cn,然后在浏览器打开这个域名后,就会出现一张壁纸,每刷新一次,就会随机出现一张新壁纸。

那么该如何接入Teek使用呢?

方案1:Teek修改代码,让自己适配这个壁纸api,博客自己 每隔8s就会 强制 请求壁纸api ,让其显示一张新壁纸

方案2:壁纸api 自己实现“每隔8s随机从 壁纸api 显示一张新壁纸”功能,但teek接入后,也需要能正常每隔8s随机从 壁纸api 显示一张新壁纸才行;

这样做的好处就是:

  1. 我们后期只需要 在壁纸api 源源不断地新增漂亮的风景照/好看的妹纸照片。我们无需修改teek的代码,而我们的网站就可以出现新增的漂亮照片;
  2. 其它Teek道友或者类型的博客也可以使用我们的壁纸api;

说明:

bash
不管怎么实现,越简单越好,能实现就好。

首先,壁纸api自身的2个功能不能变:

例如壁纸api
1. imgapi.onedayxyy.cn在自己浏览器打开,会显示一张图片,刷新一次,会切换到另一张图片
2.间隔数s后,会随机切换到下一张图片

然后在次基础上,不管是改teek的代码来适配壁纸api,还是改壁纸api的代码来适配teek,或者两个都改,由开发者自己选择最优解。

背景

经过Teek群里多次讨论,XGQ-go大佬 终于把这个功能给开发好了。💖💖💖

XGQ-go大佬 把这个 go壁纸api 项目开发完成了,那么接下来就出一个手把手文章吧。😜

image-20250925180838124

效果

2025年9月25日测试。

环境

自己在《Teek-one开源库:https://cnb.cool/onedayxyy/vitepress-theme-teek-one-public》的`6f82dbb03134b88284d5e15bd8c2dce72a202589` 版本上测试成功的。(后续版本已经集成这个代码了。)

Teek@1.4.6-2025.8.31

配置

(1)编辑docs/.vitepress/ConfigHyde/Wallaper.ts文件,将其全部替换为如下内容:

ts
// 首页壁纸 - 动态获取本地图片服务器的图片

// 壁纸服务配置 - 统一配置服务地址,一处修改全局生效
export const WALLPAPER_SERVICE_CONFIG = {
  baseUrl: 'https://imgapi.onedayxyy.cn',
  // baseUrl: 'https://imgapi.onedayxyy.cn',
  apiEndpoint: '/api/images',
  get fullUrl() {
    return `${this.baseUrl}${this.apiEndpoint}`
  }
}

// 备用图片列表(当本地服务不可用时使用)
const fallbackImages = [
  "https://img.onedayxyy.cn/images/Teek/TeekBg/1.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/2.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/3.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/4.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/5.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/6.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/7.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/8.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/9.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/10.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/11.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/12.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/13.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/14.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/15.webp", 
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/16.webp",
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/17.webp",
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/18.webp",
  // "https://img.onedayxyy.cn/images/Teek/TeekBg/19.webp",
];
// 动态获取图片列表的函数
async function fetchDynamicWallpapers(): Promise<string[]> {
  try {
    // 使用统一配置的图片服务API
    const response = await fetch(WALLPAPER_SERVICE_CONFIG.fullUrl, {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
      },
    });
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    
    const data = await response.json();
    const images = data.images || [];
    
    // 将相对路径转换为完整的服务器URL
    const wallpapers = images.map((imagePath: string) => `${WALLPAPER_SERVICE_CONFIG.baseUrl}${imagePath}`);
    
    // 如果获取到图片,返回动态图片列表,否则返回备用图片
    return wallpapers.length > 0 ? wallpapers : wallpapers;
    
  } catch (error) {
    console.warn('无法获取动态壁纸,使用备用图片:', error);
    return fallbackImages;
  }
}

// 创建一个Promise来获取壁纸
let wallpaperPromise: Promise<string[]> | null = null;

// 获取壁纸的函数
function getWallpapers(): Promise<string[]> {
  if (!wallpaperPromise) {
    wallpaperPromise = fetchDynamicWallpapers();
  }
  return wallpaperPromise;
}

// 导出的Wallpaper数组 - 在服务端渲染时使用备用图片,客户端动态加载
export const Wallpaper: string[] = fallbackImages;

// 导出动态获取函数供主题使用
export { getWallpapers, fetchDynamicWallpapers };

(2)创建docs/.vitepress/theme/components/DynamicWallpaperManager.vue文件:

vue
<template>
  <!-- 这是一个无渲染组件,仅用于管理动态壁纸 -->
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, nextTick, watch } from 'vue'
import { useRoute } from 'vitepress'
import { fetchDynamicWallpapers, WALLPAPER_SERVICE_CONFIG } from '../../ConfigHyde/Wallaper'

// 路由检测 - 只在首页启用动态壁纸
const route = useRoute()
let isHomePage = false

// 检查是否为首页
function checkIsHomePage(): boolean {
  const path = route.path
  return path === '/' || path === '/index.html' || path === ''
}

// 停止所有动态壁纸相关功能
function stopWallpaperSystem() {
  if (fetchLibraryIntervalId) {
    clearInterval(fetchLibraryIntervalId)
    fetchLibraryIntervalId = null
  }
  if (switchImageIntervalId) {
    clearInterval(switchImageIntervalId)
    switchImageIntervalId = null
  }
  stopServiceMonitoring()

  // 清理呼吸动画类
  const backgroundElements = document.querySelectorAll('.wallpaper-breathing')
  backgroundElements.forEach(element => {
    element.classList.remove('wallpaper-breathing')
  })

  console.log('🖼️ 动态壁纸系统已停止(非首页)')
}

// 启动动态壁纸系统(仅首页)
function startWallpaperSystem() {
  if (!isHomePage) return

  console.log('🖼️ 动态壁纸系统启动(首页)')
  // 壁纸系统启动逻辑将在 onMounted 中调用
}

// 定义时间间隔配置
const FETCH_LIBRARY_INTERVAL = 60 * 1000 // 60秒请求一次图集服务器获取图库
const SWITCH_IMAGE_INTERVAL = 10 * 1000 // 10秒从图库中随机选择一张图片展示
const SERVICE_CHECK_INTERVAL = 15 * 1000 // 15秒检测一次服务状态(当使用备用图片时)

let fetchLibraryIntervalId: number | null = null // 图库请求定时器
let switchImageIntervalId: number | null = null // 图片切换定时器
let serviceCheckIntervalId: number | null = null // 服务检测定时器
let currentImages: string[] = [] // 当前图库
let currentDisplayImage: string = '' // 当前展示的图片
let isUsingFallback: boolean = false // 是否正在使用备用图片
let lastSuccessfulFetch: number = 0 // 上次成功获取图库的时间

// 双图层状态管理
let currentActiveLayer: 'A' | 'B' = 'A' // 当前活动图层
let isTransitioning: boolean = false // 是否正在切换中
let layerHistory: Array<{ layer: 'A' | 'B', image: string, timestamp: number }> = [] // 图层历史记录
let pendingSwitchQueue: Array<{ image: string, timestamp: number }> = [] // 待处理的切换队列

// 缓存相关
const CACHE_KEY = 'dynamic-wallpaper-cache'
const LAST_IMAGE_KEY = 'last-wallpaper-image'

// 保存图库到缓存
function saveImagesToCache(images: string[]) {
  try {
    // 检查是否在客户端环境
    if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
      return
    }
    localStorage.setItem(CACHE_KEY, JSON.stringify(images))
  } catch (error) {
    console.warn('保存图库缓存失败:', error)
  }
}

// 从缓存加载图库
function loadImagesFromCache(): string[] {
  try {
    // 检查是否在客户端环境
    if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
      return []
    }
    const cached = localStorage.getItem(CACHE_KEY)
    return cached ? JSON.parse(cached) : []
  } catch (error) {
    console.warn('加载图库缓存失败:', error)
    return []
  }
}

// 保存最后显示的图片
function saveLastImage(imageSrc: string) {
  try {
    // 检查是否在客户端环境
    if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
      return
    }
    localStorage.setItem(LAST_IMAGE_KEY, imageSrc)
  } catch (error) {
    console.warn('保存最后图片失败:', error)
  }
}

// 获取最后显示的图片
function getLastImage(): string | null {
  try {
    // 检查是否在客户端环境
    if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
      return null
    }
    return localStorage.getItem(LAST_IMAGE_KEY)
  } catch (error) {
    console.warn('获取最后图片失败:', error)
    return null
  }
}

// 预加载图片以避免加载闪烁,检测图片是否可用
function preloadImage(src: string): Promise<boolean> {
  return new Promise((resolve) => {
    const img = new Image()

    // 设置3秒超时
    const timeout = setTimeout(() => {
      img.onload = null
      img.onerror = null
      resolve(false)
    }, 3000)

    img.onload = () => {
      clearTimeout(timeout)
      resolve(true) // 加载成功
    }
    img.onerror = () => {
      clearTimeout(timeout)
      resolve(false) // 加载失败
    }
    img.src = src
  })
}

// 获取图层状态信息
function getLayerStatus(): { currentLayer: 'A' | 'B', isTransitioning: boolean, history: typeof layerHistory } {
  return {
    currentLayer: currentActiveLayer,
    isTransitioning,
    history: [...layerHistory] // 返回副本
  }
}

// 记录图层状态到历史
function recordLayerState(layer: 'A' | 'B', image: string) {
  const now = Date.now()
  layerHistory.push({ layer, image, timestamp: now })

  // 保持历史记录在合理范围内(最多保留10条)
  if (layerHistory.length > 10) {
    layerHistory.shift()
  }

  console.log('📝 图层状态记录:', { layer, image, timestamp: now })
}

// 清理过期的待处理队列
function cleanPendingQueue() {
  const now = Date.now()
  const maxAge = 5000 // 5秒过期

  const beforeLength = pendingSwitchQueue.length
  pendingSwitchQueue = pendingSwitchQueue.filter(item => now - item.timestamp < maxAge)

  if (beforeLength !== pendingSwitchQueue.length) {
    console.log('🧹 清理过期的待处理队列:', beforeLength - pendingSwitchQueue.length, '个项目')
  }
}

// 处理待处理的切换队列
async function processPendingQueue() {
  if (isTransitioning || pendingSwitchQueue.length === 0) {
    return
  }

  // 清理过期项目
  cleanPendingQueue()

  // 获取最早的待处理项目
  const nextSwitch = pendingSwitchQueue.shift()
  if (nextSwitch) {
    console.log('📋 处理待切换队列:', nextSwitch.image)
    await updateBannerBackgroundWithCSS(nextSwitch.image)
  }
}

// 队列化切换请求
function queueSwitch(imageSrc: string) {
  const now = Date.now()

  // 如果队列中已有相同图片,移除旧的
  pendingSwitchQueue = pendingSwitchQueue.filter(item => item.image !== imageSrc)

  // 添加新的请求
  pendingSwitchQueue.push({ image: imageSrc, timestamp: now })

  console.log('📥 切换请求已加入队列:', imageSrc, '队列长度:', pendingSwitchQueue.length)

  // 尝试立即处理队列
  setTimeout(processPendingQueue, 100)
}

// 添加过渡动画样式
function addTransitionStyles(element: HTMLElement) {
  if (!element.style.transition || !element.style.transition.includes('opacity')) {
    element.style.transition = element.style.transition 
      ? `${element.style.transition}, opacity 0.3s ease-in-out`
      : 'opacity 0.3s ease-in-out'
  }
}

// 简化的内容层稳定性函数(CSS变量方案下不再需要复杂的DOM操作)
function ensureBannerContentStability() {
  // 仅确保banner容器有正确的基本设置
  const bannerEl = document.querySelector('.tk-banner') as HTMLElement
  if (bannerEl) {
    bannerEl.style.overflow = 'hidden' // 隐藏背景溢出,避免滚动条
    bannerEl.style.isolation = 'isolate'

    // 在生产环境中,立即隐藏可能的默认背景图片防止闪现
    const isProduction = import.meta.env.PROD
    if (isProduction) {
      // 立即隐藏所有可能的背景元素,防止默认图片闪现
      const allBgElements = document.querySelectorAll('.tk-banner__bg, .tk-banner-bg, [class*="banner"][class*="bg"], .banner-bg')
      allBgElements.forEach(el => {
        const element = el as HTMLElement
        element.style.opacity = '0'
        element.style.visibility = 'hidden'
        element.style.zIndex = '-1000'
      })
    }

    // 彻底清理可能冲突的旧背景元素样式
    const oldBgElements = bannerEl.querySelectorAll('.tk-banner__bg, .tk-banner-bg, [class*="banner"][class*="bg"]')
    oldBgElements.forEach(el => {
      const element = el as HTMLElement
      // 完全隐藏旧的背景元素避免格子问题
      element.style.display = 'none'
      element.style.backgroundImage = 'none'
      element.style.background = 'none'
      element.style.opacity = '0'
      element.style.zIndex = '-1000'
    })

    // 清理banner本身可能的背景样式
    bannerEl.style.backgroundImage = 'none'
    bannerEl.style.background = 'transparent'
  }
}

// CSS变量方案下,不再需要复杂的保护和调试函数
// 保留简单的调试函数用于开发
function debugBannerState() {
  const bannerEl = document.querySelector('.tk-banner') as HTMLElement
  if (bannerEl) {
    const bgImage = bannerEl.style.getPropertyValue('--banner-bg-image')
    const bgOpacity = bannerEl.style.getPropertyValue('--banner-bg-opacity')
    console.log('🔍 Banner状态:', { bgImage, bgOpacity })
  }
}

// 双图层初始化Banner背景
function initBannerBackground(imageSrc: string): boolean {
  const bannerEl = document.querySelector('.tk-banner') as HTMLElement

  if (bannerEl) {
    // 立即隐藏可能的默认Banner背景,防止闪现
    const oldBgElements = bannerEl.querySelectorAll('.tk-banner__bg, .tk-banner-bg, [class*="banner"][class*="bg"]')
    oldBgElements.forEach(el => {
      const element = el as HTMLElement
      element.style.opacity = '0'
      element.style.visibility = 'hidden'
    })

    // 使用主题背景色避免蓝色闪烁,与blogger-fix.scss保持一致
    bannerEl.style.background = 'var(--vp-c-bg)'
    bannerEl.style.backgroundColor = 'var(--vp-c-bg)'

    // 立即设置图层A并显示,避免透明状态
    bannerEl.style.setProperty('--layer-a-bg-image', `url("${imageSrc}")`)
    bannerEl.style.setProperty('--layer-a-opacity', '1') // 立即显示,不从0开始
    bannerEl.style.setProperty('--layer-b-opacity', '0')

    // 立即显示图层A类
    bannerEl.classList.remove('has-layer-b', 'dual-layer')
    bannerEl.classList.add('has-layer-a')
    currentActiveLayer = 'A'

    // 预加载图片用于验证
    const img = new Image()
    img.onload = () => {
      console.log('🎯 双图层初始化 - 图片验证成功:', imageSrc)
      // 图片加载成功后添加背景加载完成的类,移除预设背景色
      setTimeout(() => {
        bannerEl.classList.add('background-loaded')
      }, 300) // 确保图片已显示后再移除背景色
    }
    img.onerror = () => {
      console.warn('❌ 双图层初始化图片验证失败,保持预设背景:', imageSrc)
      // 图片加载失败时保持预设背景色,不添加background-loaded类
    }

    console.log('🔄 双图层系统 - 立即显示背景并验证图片:', imageSrc)
    img.src = imageSrc
    return true
  }

  console.warn('❌ 未找到.tk-banner元素')
  return false
}

// 双图层无缝切换函数 - 解决白屏问题
async function updateBannerBackgroundWithCSS(imageSrc: string): Promise<boolean> {
  const bannerEl = document.querySelector('.tk-banner') as HTMLElement

  if (!bannerEl) {
    console.warn('❌ 未找到.tk-banner元素')
    return false
  }

  // 如果正在切换中,将请求加入队列
  if (isTransitioning) {
    console.log('⏭️ 正在切换中,将请求加入队列:', imageSrc)
    queueSwitch(imageSrc)
    return false
  }

  try {
    // 预加载图片确保切换时不会有闪烁
    const preloadSuccess = await preloadImage(imageSrc)

    if (!preloadSuccess) {
      console.warn('❌ 双图层切换失败,图片预加载失败:', imageSrc)
      return false
    }

    console.log('🔄 双图层无缝切换开始 - 当前活动图层:', currentActiveLayer)

    isTransitioning = true
    const oldActiveLayer = currentActiveLayer
    const targetLayer = currentActiveLayer === 'A' ? 'B' : 'A'

    // 记录切换开始状态
    recordLayerState(oldActiveLayer, currentDisplayImage || '当前图片')

    // 1. 在非活动图层预加载新图片
    if (targetLayer === 'A') {
      bannerEl.style.setProperty('--layer-a-bg-image', `url("${imageSrc}")`)
      bannerEl.style.setProperty('--layer-a-opacity', '0')
      bannerEl.classList.add('has-layer-a', 'dual-layer') // 启用双图层显示
    } else {
      bannerEl.style.setProperty('--layer-b-bg-image', `url("${imageSrc}")`)
      bannerEl.style.setProperty('--layer-b-opacity', '0')
      bannerEl.classList.add('has-layer-b', 'dual-layer') // 启用双图层显示
    }

    // 2. 新图层淡入(此时两个图层都显示,无白屏)
    await new Promise<void>(resolve => {
      setTimeout(() => {
        if (targetLayer === 'A') {
          bannerEl.style.setProperty('--layer-a-opacity', '1')
        } else {
          bannerEl.style.setProperty('--layer-b-opacity', '1')
        }
        console.log('🔄 新图层开始淡入:', targetLayer, '透明度设为1')
        resolve()
      }, 100) // 短暂延迟确保CSS生效
    })

    // 3. 等待新图层完全显示后,隐藏旧图层
    await new Promise<void>(resolve => {
      // 等待新图层过渡动画完全结束再隐藏旧图层
      setTimeout(() => {
        console.log('🔄 新图层已完全可见,开始隐藏旧图层:', oldActiveLayer)

        // 现在开始隐藏旧图层
        if (oldActiveLayer === 'A') {
          bannerEl.style.setProperty('--layer-a-opacity', '0')
        } else {
          bannerEl.style.setProperty('--layer-b-opacity', '0')
        }

        // 等待旧图层完全隐藏后再清理类
        setTimeout(() => {
          // 移除旧图层的显示类
          if (oldActiveLayer === 'A') {
            bannerEl.classList.remove('has-layer-a')
          } else {
            bannerEl.classList.remove('has-layer-b')
          }

          // 4. 切换完成,更新状态
          currentActiveLayer = targetLayer
          bannerEl.classList.remove('dual-layer') // 关闭双图层模式
          bannerEl.classList.add('background-loaded') // 确保移除预设背景

          // 记录新的图层状态
          recordLayerState(targetLayer, imageSrc)

          isTransitioning = false
          console.log('✅ 双图层无缝切换完成 - 新活动图层:', currentActiveLayer, '图片:', imageSrc)

          // 保存当前显示的图片到缓存
          saveLastImage(imageSrc)

          resolve()
        }, 2050) // 缩短等待时间(2s + 50ms 缓冲)
      }, 1800) // 缩短新图层等待时间(1.8s)
    })

    // 处理队列中可能的待处理请求
    setTimeout(processPendingQueue, 100)

    return true

  } catch (error) {
    console.error('❌ 双图层切换过程中发生错误:', error)
    isTransitioning = false
    return false
  }
}

// 确保双图层呼吸动画同步
function ensureBreathingAnimationSync() {
  const bannerEl = document.querySelector('.tk-banner') as HTMLElement

  if (bannerEl) {
    // 通过重置animation触发同步
    const resetAnimation = () => {
      bannerEl.style.setProperty('--animation-state', 'paused')

      // 使用requestAnimationFrame确保DOM更新
      requestAnimationFrame(() => {
        bannerEl.style.setProperty('--animation-state', 'running')
        console.log('🔄 双图层呼吸动画已同步')
      })
    }

    // 在双图层模式时重置动画确保同步
    if (bannerEl.classList.contains('dual-layer')) {
      resetAnimation()
    }
  }
}

// 添加呼吸动画到所有Banner背景元素(向后兼容)
function addBreathingAnimation() {
  console.log('💨 呼吸动画已通过CSS伪元素自动启用')

  // 现在呼吸动画主要通过::before和::after伪元素实现
  // 这个函数保留用于向后兼容旧的背景元素
  const selectors = [
    '.tk-banner .tk-banner__bg',
    '.tk-banner .tk-banner-bg',
    '.tk-banner [class*="banner"][class*="bg"]',
    '.banner-bg',
    '.tk-banner-bg'
  ]

  selectors.forEach(selector => {
    const elements = document.querySelectorAll(selector)
    elements.forEach(element => {
      if (!element.classList.contains('wallpaper-breathing')) {
        element.classList.add('wallpaper-breathing')
        console.log('🌟 添加补充呼吸动画到:', selector)
      }
    })
  })

  // 确保伪元素动画同步
  ensureBreathingAnimationSync()
}

// 旧的双图层函数已被CSS变量方案替代
// 保留用于向后兼容或作为降级方案
function updateBannerBackground(imageSrc: string): boolean {
  console.warn('⚠️ 使用了旧的双图层方法,建议使用updateBannerBackgroundWithCSS')
  // 降级到CSS变量方案
  return updateBannerBackgroundWithCSS(imageSrc)
}

// 从当前图库中随机选择一张图片展示(带去重逻辑)
async function displayRandomImage() {
  // 检查图库是否为空
  if (!currentImages || currentImages.length === 0) {
    console.warn('图库为空,使用备用图片')
    currentImages = getFallbackImages()
    isUsingFallback = true
  }
  
  let availableImages = currentImages
  
  // 如果图库中有多张图片,排除当前正在展示的图片
  if (currentImages.length > 1 && currentDisplayImage) {
    availableImages = currentImages.filter(img => img !== currentDisplayImage)
  }
  
  // 如果过滤后没有图片了,使用全部图片
  if (availableImages.length === 0) {
    availableImages = currentImages
  }
  
  const randomImg = availableImages[Math.floor(Math.random() * availableImages.length)]
  
  // 如果选中的图片和当前展示的相同,直接返回(避免不必要的更新)
  if (randomImg === currentDisplayImage) return
  
  try {
    // 预加载图片并检测是否成功
    const preloadSuccess = await preloadImage(randomImg)
    
    // 如果图片加载失败且当前使用的是动态图库,切换到备用图片
    if (!preloadSuccess && !isUsingFallback) {
      console.warn('🔌 动态图片加载失败,服务可能已停止,切换到备用图片')
      currentImages = getFallbackImages()
      isUsingFallback = true
      
      // 启动服务监控
      startServiceMonitoring()
      
      // 重新从备用图库选择图片
      const fallbackImg = currentImages[Math.floor(Math.random() * currentImages.length)]
      const fallbackPreloadSuccess = await preloadImage(fallbackImg)
      
      if (fallbackPreloadSuccess) {
        currentDisplayImage = fallbackImg
        updateBannerBackground(fallbackImg)
        return
      } else {
        console.error('备用图片也加载失败')
        return
      }
    } else if (!preloadSuccess) {
      // 备用图片也加载失败,跳过此次更新
      console.warn('图片加载失败,跳过此次更新')
      return
    }
    
    // 更新当前展示图片记录
    currentDisplayImage = randomImg

    // 使用新的CSS变量方法更新Banner背景
    const success = updateBannerBackgroundWithCSS(randomImg)

    if (!success) {
      // 如果立即更新失败,等待DOM更新后再试
      await nextTick()
      updateBannerBackgroundWithCSS(randomImg)
    }
    
    // CSS变量方案下,呼吸动画通过伪元素自动应用,无需手动添加
    setTimeout(() => {
      debugBannerState() // 调试新的CSS变量状态
    }, 100)
    
    // 设置全局变量供其他组件使用
    ;(window as any).dynamicWallpapers = currentImages
    
    // 触发自定义事件
    window.dispatchEvent(new CustomEvent('wallpaper-updated', {
      detail: { images: currentImages, currentImage: randomImg, layerStatus: getLayerStatus() }
    }))

    // 开发环境下的状态检查
    if (typeof window !== 'undefined' && (window as any).location.hostname === 'localhost') {
      setTimeout(() => {
        const layerStatus = getLayerStatus()
        console.log('🔍 壁纸切换后状态检查:', {
          currentImage: randomImg,
          layerStatus,
          timestamp: new Date().toLocaleTimeString()
        })
      }, 2000) // 等待切换完全完成后检查
    }
    
    const imageType = isUsingFallback ? '备用' : '动态'
    console.log(`🎨 已切换${imageType}壁纸:`, randomImg)
    
  } catch (error) {
    console.warn('切换壁纸失败:', error)
  }
}


// 检测图集服务是否可用(快速检测,用于初始加载)
async function checkServiceAvailability(): Promise<boolean> {
  try {
    const controller = new AbortController()
    const timeoutId = setTimeout(() => controller.abort(), 2000) // 2秒快速超时,避免影响页面加载
    
    const response = await fetch(WALLPAPER_SERVICE_CONFIG.fullUrl, {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
      },
      signal: controller.signal
    })
    
    clearTimeout(timeoutId)
    
    if (!response.ok) {
      return false
    }
    
    const data = await response.json()
    if (!data.images || !Array.isArray(data.images) || data.images.length === 0) {
      return false
    }
    
    return true
  } catch (error) {
    return false
  }
}

// 服务状态监控(仅在使用备用图片时运行)
async function monitorServiceStatus() {
  if (!isUsingFallback) {
    // 如果不是使用备用图片,停止监控
    stopServiceMonitoring()
    return
  }
  
  console.log('🔍 检查图集服务状态...')
  const isServiceAvailable = await checkServiceAvailability()
  
  if (isServiceAvailable) {
    console.log('✅ 图集服务已恢复!切换回动态图库')
    
    // 停止服务监控
    stopServiceMonitoring()
    
    // 重新获取动态图库
    await fetchImageLibrary()
    
    // 立即切换到动态图片
    if (!isUsingFallback && currentImages.length > 0) {
      await displayRandomImage()
    }
  }
}

// 停止服务监控
function stopServiceMonitoring() {
  if (serviceCheckIntervalId) {
    clearInterval(serviceCheckIntervalId)
    serviceCheckIntervalId = null
    console.log('📴 停止图集服务监控')
  }
}

// 启动服务监控(仅在切换到备用图片时启动)
function startServiceMonitoring() {
  if (!serviceCheckIntervalId) {
    serviceCheckIntervalId = window.setInterval(monitorServiceStatus, SERVICE_CHECK_INTERVAL)
    console.log('👁️ 启动图集服务监控(15秒检测一次)')
  }
}

// 获取备用图片列表
function getFallbackImages(): string[] {
  // 从 Wallaper.ts 导入的备用图片
  const fallbackImages = [
    "https://img.xxdevops.cn/blog/wallpaper/bg01.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg02.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg03.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg04.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg05.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg06.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg07.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg08.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg09.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg10.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg11.webp", 
    "https://img.xxdevops.cn/blog/wallpaper/bg12.webp",
    "https://img.xxdevops.cn/blog/wallpaper/bg13.webp",
    "https://img.xxdevops.cn/blog/wallpaper/bg14.webp",
    "https://img.xxdevops.cn/blog/wallpaper/bg15.webp",
    "https://img.xxdevops.cn/blog/wallpaper/bg16.webp",
    "https://img.xxdevops.cn/blog/wallpaper/bg17.webp",
    "https://img.xxdevops.cn/blog/wallpaper/bg18.webp",
    "https://img.xxdevops.cn/blog/wallpaper/bg19.webp",
    "https://img.xxdevops.cn/blog/wallpaper/bg20.webp"
  ]
  return fallbackImages
}

// 页面刷新时从API获取新壁纸
async function fetchFreshWallpaperOnRefresh(): Promise<string | null> {
  try {
    console.log('🔄 页面刷新,从API获取新壁纸...')
    const images = await fetchDynamicWallpapers()

    // 检查是否获取到有效的动态图片(非备用图片)
    const fallbackImages = getFallbackImages()
    const isDynamicImages = images.some(img => !fallbackImages.includes(img))

    if (isDynamicImages && images.length > 0) {
      // 成功获取到动态图库
      currentImages = images
      lastSuccessfulFetch = Date.now()
      isUsingFallback = false

      // 保存图库到缓存
      saveImagesToCache(images)

      // 随机选择一张新壁纸,排除缓存的上一张
      const lastImage = getLastImage()
      let availableImages = images

      // 如果有上次的图片且图库有多张图,排除上次的图片
      if (lastImage && images.length > 1) {
        availableImages = images.filter(img => img !== lastImage)
      }

      // 如果过滤后没有图片了,使用全部图片
      if (availableImages.length === 0) {
        availableImages = images
      }

      const randomImg = availableImages[Math.floor(Math.random() * availableImages.length)]
      console.log(`🎨 刷新获取新壁纸成功: ${randomImg}`)

      return randomImg
    } else {
      throw new Error('未获取到有效的动态图片')
    }
  } catch (error) {
    console.warn('刷新获取新壁纸失败,使用备用图片:', error)

    // 使用备用图片
    const fallbackImages = getFallbackImages()
    currentImages = fallbackImages
    isUsingFallback = true

    // 保存备用图库到缓存
    saveImagesToCache(fallbackImages)

    // 启动服务监控
    startServiceMonitoring()

    // 从备用图片中随机选择
    const lastImage = getLastImage()
    let availableImages = fallbackImages

    if (lastImage && fallbackImages.length > 1) {
      availableImages = fallbackImages.filter(img => img !== lastImage)
    }

    if (availableImages.length === 0) {
      availableImages = fallbackImages
    }

    const randomImg = availableImages[Math.floor(Math.random() * availableImages.length)]
    console.log(`🔄 使用备用壁纸: ${randomImg}`)

    return randomImg
  }
}

// 从图集服务器获取图库列表
async function fetchImageLibrary() {
  try {
    const images = await fetchDynamicWallpapers()

    // 检查是否获取到有效的动态图片(非备用图片)
    const fallbackImages = getFallbackImages()
    const isDynamicImages = images.some(img => !fallbackImages.includes(img))

    if (isDynamicImages && images.length > 0) {
      // 成功获取到动态图库
      currentImages = images
      lastSuccessfulFetch = Date.now()

      // 保存图库到缓存
      saveImagesToCache(images)

      if (isUsingFallback) {
        console.log('✅ 图集服务已恢复,切换回动态图库')
        isUsingFallback = false
        // 停止服务监控
        stopServiceMonitoring()
      }

      console.log(`📚 动态图库已更新: ${images.length} 张图片`)
    } else {
      // 没有获取到有效的动态图片,使用备用图片
      if (!isUsingFallback) {
        console.log('⚠️ 图集服务不可用,切换到备用图片')
        currentImages = fallbackImages
        isUsingFallback = true
        // 启动服务监控
        startServiceMonitoring()
      }
    }
  } catch (error) {
    console.warn('获取图库失败,使用备用图片:', error)

    if (!isUsingFallback) {
      currentImages = getFallbackImages()
      isUsingFallback = true
      // 启动服务监控
      startServiceMonitoring()
    }
  }
}

onMounted(async () => {
  // 检查是否为首页
  isHomePage = checkIsHomePage()
  console.log('🖼️ 动态壁纸管理器启动 - 当前页面:', route.path, '是否首页:', isHomePage)

  if (!isHomePage) {
    console.log('⏹️ 非首页,动态壁纸系统不启动')
    return
  }

  // 在生产构建时,增加延迟确保DOM完全ready
  const isProduction = import.meta.env.PROD
  const mountDelay = isProduction ? 100 : 0
  
  // 使用setTimeout确保在hydration完成后再执行
  setTimeout(async () => {
    // 确保banner容器正确设置
    ensureBannerContentStability()

    // 显示主题背景色作为加载状态,避免空白
    const bannerEl = document.querySelector('.tk-banner') as HTMLElement
    if (bannerEl) {
      bannerEl.style.background = 'var(--vp-c-bg)'
      bannerEl.style.backgroundColor = 'var(--vp-c-bg)'
      console.log('🎨 设置加载背景色,避免空白显示')
    }

    // 优先从API获取新的壁纸
    try {
      const freshWallpaper = await fetchFreshWallpaperOnRefresh()
      if (freshWallpaper) {
        currentDisplayImage = freshWallpaper
        // 使用新获取的壁纸立即显示
        const success = initBannerBackground(freshWallpaper)
        if (success) {
          console.log('🎯 页面刷新成功显示新壁纸:', freshWallpaper)
        } else {
          throw new Error('壁纸显示失败')
        }
      } else {
        throw new Error('未获取到新壁纸')
      }
    } catch (error) {
      console.warn('从API获取新壁纸失败,使用降级方案:', error)

      // 降级方案:使用缓存或备用壁纸
      const lastImage = getLastImage()
      const cachedImages = loadImagesFromCache()

      if (lastImage) {
        console.log('📦 降级:使用缓存的上次壁纸:', lastImage)
        currentDisplayImage = lastImage
        initBannerBackground(lastImage)

        if (cachedImages.length > 0) {
          currentImages = cachedImages
        } else {
          currentImages = getFallbackImages()
        }
      } else if (cachedImages.length > 0) {
        console.log('📦 降级:使用缓存图库随机壁纸')
        currentImages = cachedImages
        const randomImg = cachedImages[Math.floor(Math.random() * cachedImages.length)]
        currentDisplayImage = randomImg
        initBannerBackground(randomImg)
      } else {
        console.log('📦 降级:使用备用壁纸')
        currentImages = getFallbackImages()
        const randomImg = currentImages[Math.floor(Math.random() * currentImages.length)]
        currentDisplayImage = randomImg
        initBannerBackground(randomImg)
      }
    }
  }, mountDelay)

  // 页面可见性变化监听 - 优化性能
  const handleVisibilityChange = () => {
    const bannerEl = document.querySelector('.tk-banner') as HTMLElement

    if (bannerEl) {
      if (document.hidden) {
        // 页面隐藏时暂停伪元素动画
        bannerEl.classList.add('paused')
      } else {
        // 页面可见时恢复伪元素动画
        bannerEl.classList.remove('paused')
      }
    }

    // 同时处理其他可能的背景元素
    const backgroundElements = document.querySelectorAll('.wallpaper-breathing')
    backgroundElements.forEach(element => {
      if (document.hidden) {
        element.classList.add('paused')
      } else {
        element.classList.remove('paused')
      }
    })
  }

  document.addEventListener('visibilitychange', handleVisibilityChange)
  
  // 等待一个切换间隔后开始异步检测和切换
  setTimeout(async () => {
    console.log('🔍 开始检测图集服务状态并更新图库...')

    try {
      const controller = new AbortController()
      const timeoutId = setTimeout(() => controller.abort(), 2000) // 2秒检测

      const response = await fetch(WALLPAPER_SERVICE_CONFIG.fullUrl, {
        method: 'GET',
        headers: { 'Accept': 'application/json' },
        signal: controller.signal
      })

      clearTimeout(timeoutId)

      if (response.ok) {
        // 服务可用:获取最新图库
        console.log('✅ 图集服务可用,更新动态图库')
        await fetchImageLibrary()

        // 设置定时器:每60秒更新图库
        fetchLibraryIntervalId = window.setInterval(fetchImageLibrary, FETCH_LIBRARY_INTERVAL)
      } else {
        throw new Error('服务响应异常')
      }
    } catch (error) {
      // 服务不可用:确保使用备用图片并启动监控
      console.log('❌ 图集服务不可用,确保使用备用壁纸')
      if (!isUsingFallback) {
        currentImages = getFallbackImages()
        isUsingFallback = true
        saveImagesToCache(currentImages) // 保存备用图库到缓存
      }

      // 启动服务监控,等待服务恢复
      startServiceMonitoring()
    }
  }, isProduction ? 1500 : 1000) // 生产环境增加延迟,确保缓存壁纸已显示
  
  // 设置定时器:每10秒切换图片(确保统一的切换间隔)
  switchImageIntervalId = window.setInterval(displayRandomImage, SWITCH_IMAGE_INTERVAL)
  console.log(`⏰ 壁纸切换定时器已启动,间隔: ${SWITCH_IMAGE_INTERVAL / 1000}秒`)

  // 初始化基本设置(CSS变量方案下大大简化)
  setTimeout(() => {
    ensureBannerContentStability()
    console.log('🌟 CSS变量背景系统初始化完成')
  }, 500)

  // 监听路由变化
  watch(() => route.path, (newPath) => {
    const newIsHomePage = checkIsHomePage()
    console.log('🧭 路由变化:', newPath, '是否首页:', newIsHomePage)

    if (newIsHomePage !== isHomePage) {
      isHomePage = newIsHomePage

      if (isHomePage) {
        console.log('🏠 切换到首页,启动动态壁纸系统')
        // 如果切换回首页,重新启动系统(但此时组件应该重新挂载)
        location.reload() // 简单重载确保干净状态
      } else {
        console.log('🚪 离开首页,停止动态壁纸系统')
        stopWallpaperSystem()
      }
    }
  })
})

onUnmounted(() => {
  // 清理图库获取定时器
  if (fetchLibraryIntervalId) {
    clearInterval(fetchLibraryIntervalId)
    fetchLibraryIntervalId = null
  }
  
  // 清理图片切换定时器  
  if (switchImageIntervalId) {
    clearInterval(switchImageIntervalId)
    switchImageIntervalId = null
  }
  
  // 清理服务检测定时器
  stopServiceMonitoring()

  // 清理页面可见性监听器
  document.removeEventListener('visibilitychange', () => {})

  console.log('🖼️ 动态壁纸管理器已停止')
})
</script>

<style>
/* 壁纸呼吸动画效果 - 增强可见性版本 */
@keyframes wallpaper-breathing {
  0%, 100% {
    transform: scale(1) translateZ(0);
    filter: brightness(1) contrast(1) saturate(1);
  }
  50% {
    transform: scale(1.025) translateZ(0); /* 增加缩放幅度让效果更明显 */
    filter: brightness(1.12) contrast(1.05) saturate(1.05); /* 增强滤镜效果 */
  }
}

/* 呼吸动画类 - 限制为首页专用,避免影响其他页面 */
.VPHome .wallpaper-breathing,
.VPHome .tk-banner .wallpaper-breathing,
.VPHome .tk-banner .tk-banner__bg.wallpaper-breathing,
.VPHome .tk-banner .tk-banner-bg.wallpaper-breathing,
.VPHome [style*="background-image"].wallpaper-breathing {
  animation: wallpaper-breathing 6s ease-in-out infinite !important;
  transform-origin: center center !important;
  will-change: transform, filter;
}

/* 壁纸淡入淡出过渡样式 - 确保背景图片层次正确 */
.tk-banner .tk-banner__bg,
.tk-banner .tk-banner-bg,
.tk-banner [class*="banner"][class*="bg"],
.banner-bg,
.tk-banner-bg,
.background-image {
  background-blend-mode: normal;
  /* 确保多层背景正确显示 */
  /* 添加硬件加速以获得更流畅的过渡 */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translateZ(0);
  /* 预设过渡效果,使用最佳的缓动函数 */
  transition: opacity 1.5s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  /* 确保图片切换时不会有空白背景 */
  background-color: transparent;
  /* 优化渲染性能 */
  will-change: opacity, transform;
}

/* 确保背景图片容器有足够的层级 */
[style*="background-image"] {
  position: relative;
  overflow: hidden;
  /* 添加硬件加速 */
  transform: translateZ(0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* 优化过渡效果 */
  transition: opacity 1.5s cubic-bezier(0.4, 0, 0.2, 1);
  /* 确保无背景色干扰 */
  background-color: transparent;
  /* 优化渲染性能 */
  will-change: opacity;
}

/* 双图层无缝切换背景系统 - 限制为首页专用 */
.VPHome .tk-banner {
  position: relative;
  z-index: 0;
  overflow: hidden; /* 隐藏背景溢出,避免产生滚动条 */
  /* 创建独立的层叠上下文但不影响子元素 */
  isolation: isolate;

  /* 使用主题背景色避免蓝色闪烁,与blogger-fix.scss保持一致 */
  background: var(--vp-c-bg);
  background-color: var(--vp-c-bg);

  /* 图层A的CSS变量 */
  --layer-a-bg-image: none;
  --layer-a-opacity: 0;

  /* 图层B的CSS变量 */
  --layer-b-bg-image: none;
  --layer-b-opacity: 0;

  /* 通用控制变量 */
  --bg-transition-duration: 2s;
}

/* 生产环境防闪现优化 - 立即隐藏可能的默认背景元素 */
.VPHome .tk-banner .tk-banner__bg,
.VPHome .tk-banner .tk-banner-bg,
.VPHome .tk-banner [class*="banner"][class*="bg"],
.VPHome .banner-bg {
  opacity: 0 !important;
  visibility: hidden !important;
  z-index: -1000 !important;
  transition: none !important;
}

/* 图层A - 使用::before伪元素 - 限制为首页专用 */
.VPHome .tk-banner::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image: var(--layer-a-bg-image);
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-color: transparent;
  opacity: var(--layer-a-opacity);
  transition: opacity var(--bg-transition-duration) cubic-bezier(0.4, 0, 0.2, 1);
  z-index: -2; /* 在图层B下方 */
  pointer-events: none;
  /* 硬件加速 */
  will-change: opacity, transform, filter;
  backface-visibility: hidden;
  transform: translateZ(0);
  /* 呼吸动画 - 图层A,同步时机 */
  animation: wallpaper-breathing 8s ease-in-out infinite;
  animation-delay: 0s;
  transform-origin: center center;
}

/* 图层B - 使用::after伪元素 - 限制为首页专用 */
.VPHome .tk-banner::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image: var(--layer-b-bg-image);
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-color: transparent;
  opacity: var(--layer-b-opacity);
  transition: opacity var(--bg-transition-duration) cubic-bezier(0.4, 0, 0.2, 1);
  z-index: -1; /* 在图层A上方 */
  pointer-events: none;
  /* 硬件加速 */
  will-change: opacity, transform, filter;
  backface-visibility: hidden;
  transform: translateZ(0);
  /* 呼吸动画 - 图层B,与图层A完全同步 */
  animation: wallpaper-breathing 8s ease-in-out infinite;
  animation-delay: 0s;
  transform-origin: center center;
}

/* 图层显示控制 - 限制为首页专用 */
/* 默认状态下两个图层都显示但透明 */
.VPHome .tk-banner::before,
.VPHome .tk-banner::after {
  display: block;
  opacity: 0;
}

/* 有背景时显示对应图层 */
.VPHome .tk-banner.has-layer-a::before {
  display: block;
  opacity: var(--layer-a-opacity);
}

.VPHome .tk-banner.has-layer-b::after {
  display: block;
  opacity: var(--layer-b-opacity);
}

/* 图层加载完成后移除预设背景 */
.VPHome .tk-banner.has-layer-a.background-loaded,
.VPHome .tk-banner.has-layer-b.background-loaded {
  background: none !important;
  background-color: transparent !important;
}

/* 双图层同时显示时用于无缝切换 */
.VPHome .tk-banner.dual-layer::before,
.VPHome .tk-banner.dual-layer::after {
  display: block;
}

/* 页面隐藏时暂停两个图层的动画 */
.VPHome .tk-banner.paused::before,
.VPHome .tk-banner.paused::after {
  animation-play-state: paused;
}

/* 动画时机优化 - 确保图层可见时播放动画 */
.VPHome .tk-banner.has-layer-a::before {
  animation-play-state: running;
}

.VPHome .tk-banner.has-layer-b::after {
  animation-play-state: running;
}

/* 默认情况下也允许动画运行,避免动画被意外暂停 */
.VPHome .tk-banner::before,
.VPHome .tk-banner::after {
  animation-play-state: running;
}

/* 双图层模式下确保两个动画同步 */
.VPHome .tk-banner.dual-layer::before,
.VPHome .tk-banner.dual-layer::after {
  animation-play-state: running;
  /* 确保两个图层的动画开始时间一致 */
  animation-delay: 0s;
}

/* 移动端优化呼吸动画 - 应用到双图层 - 限制为首页专用 */
@media (max-width: 768px) {
  .VPHome .tk-banner::before,
  .VPHome .tk-banner::after {
    animation-duration: 12s;
    /* 移动端减少性能消耗 */
    will-change: opacity;
  }

  /* 移动端呼吸动画重定义 */
  @keyframes wallpaper-breathing {
    0%, 100% {
      transform: scale(1) translateZ(0);
      filter: brightness(1);
    }
    50% {
      transform: scale(1.008) translateZ(0); /* 移动端进一步减少缩放 */
      filter: brightness(1.05);
    }
  }
}

/* 保留旧背景元素的动画支持,但优先使用伪元素 - 限制为首页专用 */
.VPHome .tk-banner .tk-banner__bg,
.VPHome .tk-banner .tk-banner-bg,
.VPHome .tk-banner [class*="banner"][class*="bg"] {
  animation: wallpaper-breathing 8s ease-in-out infinite;
  transform-origin: center center;
  will-change: transform, filter;
}

.VPHome .tk-banner .wallpaper-breathing {
  animation-duration: 10s;
}

/* 移动端旧背景元素呼吸动画优化 */
@media (max-width: 768px) {
  .VPHome .wallpaper-breathing {
    animation-duration: 12s; /* 移动端使用更缓慢的呼吸频率 */
  }
}

/* 暂停动画的类(用于页面切换时) - 限制为首页专用 */
.VPHome .wallpaper-breathing.paused {
  animation-play-state: paused;
}

/* 临时图层样式(现在主要用于向后兼容) */
.wallpaper-temp-layer {
  backface-visibility: hidden;
  transform: translateZ(-1px);
  will-change: opacity;
  z-index: -50;
  position: absolute;
  pointer-events: none;
}

/* 确保过渡期间不会有闪烁 */
.tk-banner .tk-banner__bg,
.tk-banner .tk-banner-bg,
.tk-banner [class*="banner"][class*="bg"] {
  /* 防止在切换时显示空白背景 */
  min-height: 100%;
  background-attachment: local;
}

/* 简化的内容层保护 - 基于CSS变量的稳定方案 */
.tk-banner-content,
.tk-banner .tk-banner-content,
.banner-content {
  position: relative;
  z-index: 10;
  /* 确保内容层稳定显示 */
  isolation: isolate;
  /* 确保内容区域不被隐藏的背景overflow影响 */
  overflow: visible;
}

/* 所有banner内容子元素的基本保护 */
.tk-banner-content *,
.tk-banner .tk-banner-content * {
  position: relative;
  z-index: 11;
}

/* 确保所有banner内部内容都不受背景overflow:hidden影响 */
.tk-banner > *:not(::before):not(::after) {
  position: relative;
  z-index: 5;
  /* 确保内容层有自己的显示空间 */
  overflow: visible;
}

/* 特别保护常见的banner内容元素 */
.tk-banner .tk-banner-title,
.tk-banner .tk-banner-subtitle,
.tk-banner .tk-banner-description,
.tk-banner .tk-banner-buttons,
.tk-banner .banner-content,
.tk-banner .banner-text {
  position: relative;
  z-index: 15;
  overflow: visible;
}

/* 确保旧的背景元素正确定位 */
.tk-banner .tk-banner__bg,
.tk-banner .tk-banner-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  pointer-events: none;
}

/* 确保banner的层级结构正确 - 限制为首页专用 */
.VPHome .tk-banner {
  /* 确保banner容器有合适的层级上下文 */
  z-index: 1;
}

.VPHome .tk-banner > *:not(.tk-banner__bg):not(.tk-banner-bg):not([class*="banner"][class*="bg"]) {
  /* 确保所有非背景的banner子元素都在背景之上 */
  position: relative;
  z-index: 2;
}
</style>

(3)修改docs\index.md文件:

添加如下2行内容:

ts
import DynamicWallpaperManager from "./.vitepress/theme/components/DynamicWallpaperManager.vue"; //导入壁纸api组件


<!-- 首页专用动态壁纸组件 -->
<DynamicWallpaperManager />

image-20250925183551395

image-20250925183527972

(4)创建docs\.vitepress\theme\style\blogger-fix.scss文件:

scss
/* 修复博主信息卡片背景图层级问题 */

/* 覆盖壁纸加载时的蓝色背景闪烁 */
.tk-banner {
  /* 只在非首页移除背景,首页保留动态壁纸功能 */
  background: transparent !important;
  background-color: transparent !important;
}

/* 首页动态壁纸专用样式 - 优先级更高 */
.VPHome .tk-banner {
  background: var(--vp-c-bg) !important;
  background-color: var(--vp-c-bg) !important;
}

/* 壁纸加载完成后移除预设背景 */
.VPHome .tk-banner.background-loaded {
  background: none !important;
  background-color: transparent !important;
}

/* 确保背景图在最底层 */
.tk-my__avatar__circle--bg {
  position: absolute !important;
  z-index: 1 !important;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-size: cover !important;
  background-position: center !important;
  background-repeat: no-repeat !important;
}

/* 确保头像在背景图之上 */
.tk-my__avatar {
  position: relative !important;
  z-index: 2 !important;
}

/* 确保博主信息文字在背景图之上 */
.tk-my__blogger {
  position: relative !important;
  z-index: 2 !important;
  color: #fff !important;
}

/* 确保社交图标在背景图之上 */
.tk-my__icons {
  position: relative !important;
  z-index: 2 !important;
}

/* 确保整个博主信息卡片有正确的层级结构 */
.tk-my.is-circle-bg {
  position: relative !important;
  overflow: hidden;
}

/* 优化文字可读性 */
.tk-my__blogger .name {
  color: #fff !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
  font-weight: bold;
}

.tk-my__blogger .slogan {
  color: rgba(255, 255, 255, 0.9) !important;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

再编辑下docs\.vitepress\theme\style\index.scss文件:(使用下刚才创建的scss文件)

scss
@use "./blogger-fix.scss" as *; // 修复博主信息卡片背景图层级问题

(5)验证。

运行项目,验证效果。pnpm docs:dev

效果见上文。(完美😜)

总结

以上我们的Go壁纸api 就接入Teek了,此时你只需要有空把好看的妹纸、风景照片存到 壁纸api后台,Teek首页就会立马看到你的好看照片了哦。😜(快去试试吧)

https://zdir.onedayxyy.cn/#/

image-20250925185654812

扩展

关于我的 go壁纸api 项目是如何部署的,请看开源链接《img-server

image-20250925185428289

结束。

最近更新