--- /** * 详情页图集体(走秀 / 街拍共用)。 * * 设计动机:RunwayLookCard 与 StreetSnapCard 的「标题 + 图集网格 + 未登录占位遮罩 + 大图/副图灯箱」 * 逐块同构,差异只有几处声明式开关: * - aspect 主图与灯箱缩略图比例(当前两页都 2/3 —— 后端素材统一 2:3,见下方 prop 说明) * - showCaptions 图注:街拍有(图片名),走秀无 * - countLabel 工具栏计数文案:LOOKS / PHOTOS * - defaultDensity 默认每行张数(走秀与街拍均 5,都可在工具栏切到 3) * - kind 决定已登录补全量用哪个取数函数(走秀/街拍各一个接口) * - slot after-grid 图集之后的内容(走秀的系列描述;街拍没有) * * 故把「不变的标记」收口在本组件,把上面这些差异用 props / 插槽注入; * 页面级差异(SSR 取数、TDK、meta.type、标题里的 \t 归一)仍留在两个详情视图与两个薄壳里。 * * 与灯箱的关系:大图灯箱 GalleryLightbox / 副图灯箱 GalleryDetailLightbox / 交互 lib/gallery.ts * 早就共享;本组件只是把它们的装配(含 details 插槽)也一并收口。 * * ⚠️ Alpine 脚本注意:脚本是打包模块,读不到 props,故 rootId / alpineName / kind / favType / * defaultDensity 全部经根节点 data-* 传下去,脚本在 alpine:init 时读一次。 */ import GalleryLightbox from "@/components/GalleryLightbox.astro" import GalleryDetailLightbox from "@/components/GalleryDetailLightbox.astro" import DetailCountBadge from "@/components/DetailCountBadge.astro" import LbDetailsStrip from "@/components/LbDetailsStrip.astro" import { getI18n } from "@/lib/i18n" interface GalleryImage { id: string url: string thumb: string raw: string name: string } interface Props { /** 模块身份:决定已登录补全量走哪个详情接口(runway=图集接口 / street=街拍接口) */ kind: "runway" | "street" /** 根节点 id(灯箱交互靠它查根元素上的 data-*) */ rootId: string /** Alpine 组件注册名(两个页面各一个,避免同名互相覆盖) */ alpineName: string /** 图集网格 id(灯箱按它查 [data-image-index] / [data-fav-id]) */ galleryId: string /** 单图收藏类型:runway_image | snap_image */ favType: string /** * 主图与灯箱缩略图比例。 * 后端素材统一 2:3(实测 S4 原图 240×360、high 样式 720×1080,宽高比均 0.6667), * 故走秀与街拍都传 "2/3" —— 此时 object-cover 零裁切;写成 3/4 会把 2:3 的图 * 强行按 0.75 裁掉上下各约 11%(一行 5 张、格子变小时尤其明显)。 * 保留本 prop 只是为将来某模块素材比例真的不同时能单独覆盖,不是"两页各一套"。 */ aspect: "2/3" | "3/4" /** 是否取到了实体(false 时渲染「缺 id / 取数失败」空态)。不用 title 代替:标题允许为空 */ hasItem: boolean /** H1 文案(调用方已处理好多语言 / \t 归一) */ title: string /** SSR 首屏图片(调用方已切到 PREVIEW_LIMIT 张) */ previewImages: GalleryImage[] /** 工具栏计数(真实总数优先) */ totalCount: number /** 计数单位文案:LOOKS / PHOTOS */ countLabel: string /** 后端截断了图集(未登录) */ preview: boolean /** 占位遮罩格数(补足「剩余 N 张」) */ lockedCount: number /** 递给客户端的副图投影(id + detail),与登录后完整 images 同构解析 */ detailPayload: unknown /** 图集元信息:写进 data-*,供收藏 / 灯箱使用 */ galleryUid: string galleryTitle: string galleryBrand: string /** 是否渲染图片名图注(街拍有、走秀无) */ showCaptions?: boolean /** 默认每行张数(移动端固定 2 列,此值只影响 md+) */ defaultDensity?: 3 | 5 /** 取数失败 / 缺 id 时的提示文案(调用方已按语言算好) */ errorText: string /** 空态返回首页链接 */ homeHref: string } const { kind, rootId, alpineName, galleryId, favType, aspect, hasItem, title, previewImages, totalCount, countLabel, preview, lockedCount, detailPayload, galleryUid, galleryTitle, galleryBrand, showCaptions = false, defaultDensity = 5, errorText, homeHref, } = Astro.props const { t } = getI18n(Astro) // 两个字面量都出现在本文件源码里,保证 Tailwind v4 JIT 能扫描到 const imgAspect = aspect === "3/4" ? "aspect-[3/4]" : "aspect-[2/3]" const hasImages = previewImages.length > 0 ---
{errorText}
← {t('Back to Index')}