84 lines
3.4 KiB
Plaintext
84 lines
3.4 KiB
Plaintext
---
|
||
/**
|
||
* 街拍详情卡片(薄壳)。
|
||
*
|
||
* 只负责街拍特有的事:把后端 RawStreetSnap 映射成图集数据、算未登录占位格数、
|
||
* 把标题里的字面 \t(地点 \t 场次)归一成 " · "。标记与交互全部交给共享的
|
||
* DetailGalleryView(与走秀同一套),差异经 props 声明:带图片名图注等。
|
||
*/
|
||
import type { RawStreetSnap } from "@/lib/api"
|
||
import DetailGalleryView from "@/components/DetailGalleryView.astro"
|
||
import { getI18n } from "@/lib/i18n"
|
||
import { href, ROUTES } from '@/lib/routes'
|
||
import { ssrAbs } from "@/lib/request"
|
||
|
||
interface Props {
|
||
snap: RawStreetSnap | null
|
||
error?: "missing" | "failed" | null
|
||
preview?: boolean // 后端未登录截断图片集时返回 true,详情页据此弹「登录查看全部图片」门禁
|
||
imageTotal?: number // 图片集真实总数(后端截断前),渲染「剩余 N 张」占位遮罩
|
||
}
|
||
|
||
const { snap, error = null, preview = false, imageTotal = 0 } = Astro.props
|
||
const { locale, t } = getI18n(Astro)
|
||
|
||
const images = (snap?.images ?? [])
|
||
.map((im) => ({
|
||
id: im.id ?? "",
|
||
url: ssrAbs(im.image || ""),
|
||
// 缩略图:灯箱左栏缩略图条只显示 76~118px,用后端给的 thumb 即可;未返回时回落展示图。
|
||
thumb: ssrAbs(im.thumb || im.image || ""),
|
||
raw: im.image || "", // 相对路径:收藏快照存相对地址,不把宿主/端口写死进库
|
||
name: im.name || "",
|
||
}))
|
||
.filter((im) => im.url)
|
||
|
||
// 递给浏览器端 Alpine 的副图数据:只序列化「带副图的主图」投影(id + detail),
|
||
// 供 lib/galleryDetail.ts 构建 主图id → 副图 映射(与登录后完整 images 同构解析)。
|
||
const detailPayload = (snap?.images ?? [])
|
||
.filter((im) => (im.detail?.length ?? 0) > 0)
|
||
.map((im) => ({ id: im.id ?? "", detail: im.detail }))
|
||
|
||
// 未登录预览上限:详情页(图集)未登录最多展示前 PREVIEW_LIMIT 张图片;其余由登录门禁提示,
|
||
// 已登录(客户端 loadAuthedState 拉全量)或图片本就不超上限时全部展示。前 PREVIEW_LIMIT 张服务端已渲染(SEO/无 JS 友好)。
|
||
const PREVIEW_LIMIT = 5
|
||
const previewImages = images.slice(0, PREVIEW_LIMIT)
|
||
|
||
// 未登录预览占位遮罩数:补足「剩余 N 张」空图,提示登录后可见,避免误以为图集只有预览上限那几张。
|
||
// 已登录(preview=false)或图片本就不超上限时 lockedCount=0,不渲染占位。
|
||
const lockedCount = preview ? Math.max(0, (imageTotal || 0) - previewImages.length) : 0
|
||
|
||
const homeHref = href(locale, ROUTES.home)
|
||
|
||
// theimpression 标题含字面 \t:地点 \t 场次,列表/详情统一以 " · " 呈现
|
||
const displayTitle = (snap?.title || "").replace(/\t/g, " · ")
|
||
|
||
const errorText = error === "missing"
|
||
? t('No street snap ID specified')
|
||
: t('Failed to load street snap. Please refresh or try later.')
|
||
---
|
||
|
||
<DetailGalleryView
|
||
kind="street"
|
||
rootId="street-snap-view"
|
||
alpineName="streetSnapView"
|
||
galleryId="snap-gallery"
|
||
favType="snap_image"
|
||
aspect="2/3"
|
||
hasItem={!!snap}
|
||
title={displayTitle}
|
||
previewImages={previewImages}
|
||
totalCount={imageTotal || images.length}
|
||
countLabel="PHOTOS"
|
||
preview={preview}
|
||
lockedCount={lockedCount}
|
||
detailPayload={detailPayload}
|
||
galleryUid={snap?.id ?? ""}
|
||
galleryTitle={displayTitle}
|
||
galleryBrand=""
|
||
showCaptions
|
||
defaultDensity={5}
|
||
errorText={errorText}
|
||
homeHref={homeHref}
|
||
/>
|