Files
frontend_v2/src/components/StreetSnapCard.astro
toom1996 f8ff5b86c7 update
2026-09-25 11:32:11 +08:00

84 lines
3.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
/**
* 街拍详情卡片(薄壳)。
*
* 只负责街拍特有的事:把后端 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}
/>