--- import { Picture } from "astro:assets"; import * as path from "node:path"; import type { ImageMetadata } from "astro"; import { coverImageConfig } from "@/config/coverImageConfig"; import type { ImageFormat, ResponsiveImageLayout } from "@/types/config"; import { getFallbackFormat, getImageFormats, getImageQuality, } from "@/utils/image-utils"; import { url } from "@/utils/url-utils"; interface Props { id?: string; src: string; class?: string; alt?: string; position?: string; basePath?: string; preview?: boolean; layout?: ResponsiveImageLayout; formats?: ImageFormat[]; loading?: "lazy" | "eager"; } const { id, src, alt, position = "center", basePath = "/", preview = false, layout = "constrained", formats = getImageFormats(), loading = "lazy", } = Astro.props; const configQuality = getImageQuality(); const fallbackFormat = getFallbackFormat(); const className = Astro.props.class; // 判断图片类型 const isLocal = !( src.startsWith("/") || src.startsWith("http") || src.startsWith("https") || src.startsWith("data:") ); const isPublic = src.startsWith("/"); // 动态导入本地图片 let img: ImageMetadata | null = null; if (isLocal) { const files = import.meta.glob( "../../**/*.{png,jpg,jpeg,webp,avif}", { import: "default", }, ); const normalizedPath = path .normalize(path.join("../../", basePath, src)) .replace(/\\/g, "/"); const file = files[normalizedPath]; if (file) { img = await file(); } else { console.error( `[ERROR] Image not found: ${normalizedPath.replace("../../", "src/")}`, ); } } // 加载回退图片 let fallbackImg: ImageMetadata | null = null; const fallbackPath = coverImageConfig.randomCoverImage.fallback; if (fallbackPath && !isLocal) { const files = import.meta.glob( "../../**/*.{png,jpg,jpeg,webp,avif}", { import: "default", }, ); const normalizedFallbackPath = path .normalize(path.join("../../", fallbackPath)) .replace(/\\/g, "/"); const file = files[normalizedFallbackPath]; if (file) { fallbackImg = await file(); } } // 图片样式 const imageClass = "w-full h-full object-cover"; const imageStyle = `object-position: ${position};`; // 响应式配置 const widths = preview ? [320, 480, 640, 960] : [800, 1200, 1600, 2000]; const sizes = preview ? "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 320px" : "(max-width: 768px) 100vw, (max-width: 1200px) 90vw, 1200px"; const quality = preview ? Math.round(configQuality * 0.9) : configQuality; // 是否显示加载动画 const showLoading = coverImageConfig.randomCoverImage.showLoading ?? true; ---
{showLoading && (
)} {fallbackImg && ( )} {isLocal && img && ( )} {!isLocal && ( {alt )}