'use client' import Image, { type ImageProps } from 'next/image' import { useEffect, useState, type SyntheticEvent } from 'react' import { BRAND_LOGO_FALLBACK_TEXT, DEFAULT_HEADER_LOGO_URL, } from '@/lib/brand-assets' type BrandLogoProps = Omit & { src?: string | null alt?: string fallbackSrc?: string fallbackText?: string onError?: (event: SyntheticEvent) => void } function resolveInitialSource(src: string | null | undefined, fallbackSrc: string) { return typeof src === 'string' && src.trim() ? src.trim() : fallbackSrc } /** * 品牌 Logo 的单次回退组件:远端失败后只切换一次本地资源; * 如果本地资源也失败,则显示稳定的文字标记,避免 onError 无限循环。 */ export default function BrandLogo({ src, alt = '', fallbackSrc = DEFAULT_HEADER_LOGO_URL, fallbackText = BRAND_LOGO_FALLBACK_TEXT, onError, className, style, width, height, ...imageProps }: BrandLogoProps) { const initialSource = resolveInitialSource(src, fallbackSrc) const [currentSource, setCurrentSource] = useState(initialSource) const [showTextFallback, setShowTextFallback] = useState(false) useEffect(() => { setCurrentSource(initialSource) setShowTextFallback(false) }, [initialSource]) const handleImageError = (event: SyntheticEvent) => { onError?.(event) if (currentSource !== fallbackSrc) { setCurrentSource(fallbackSrc) return } setShowTextFallback(true) } if (showTextFallback) { return ( {fallbackText} ) } return ( {alt} ) }