diff --git a/src/components/DetailCountBadge.astro b/src/components/DetailCountBadge.astro new file mode 100644 index 0000000..8208560 --- /dev/null +++ b/src/components/DetailCountBadge.astro @@ -0,0 +1,29 @@ +--- +// 网格主图左下角的「细节图 / 副图 张数」角标:有则显示(图层图标 + 数字),点它直接开细节灯箱; +// 纯主图(无细节图)不渲染。数量走 Alpine 的 detailCount()(响应式)—— 未登录取前 PREVIEW_LIMIT 张 +// 的细节子树,登录后由 gallery:full 重建映射,两态共用同一条渲染路径。 +// +// look:Alpine 表达式,表示该主图的 look_index。SSR 首屏传字面量(如 "3"), +// 客户端补拉的 x-for 里传表达式(如 "im.lookIndex")。 +interface Props { + look: string +} +const { look } = Astro.props +const count = `detailCount(${look})` +--- + + diff --git a/src/components/GalleryDetailLightbox.astro b/src/components/GalleryDetailLightbox.astro new file mode 100644 index 0000000..4519531 --- /dev/null +++ b/src/components/GalleryDetailLightbox.astro @@ -0,0 +1,115 @@ +--- +// 细节图 / 副图 灯箱:由主图大图灯箱里的细节缩略条打开的「单图放大」层。 +// 走秀(RunwayLookCard)与街拍(StreetSnapCard)共用;交互在 lib/galleryDetail.ts。 +import { getI18n } from "@/lib/i18n" + +const { t } = getI18n(Astro) +--- + + diff --git a/src/components/LbDetailsStrip.astro b/src/components/LbDetailsStrip.astro new file mode 100644 index 0000000..ddfff33 --- /dev/null +++ b/src/components/LbDetailsStrip.astro @@ -0,0 +1,26 @@ +--- +// 大图灯箱右下角的「当前主图的细节图 / 副图」缩略簇,注入 GalleryLightbox 的 details 具名插槽。 +// 主图放大(lbZoomed)时整簇隐藏;点其中一张进细节灯箱看大图。 +// 走秀与街拍共用,故不放任何页面专有逻辑(只读 lib/galleryDetail.ts 的 currentDetailList)。 +--- + +
+ Details +
+ +
+
diff --git a/src/components/RunwayLookCard.astro b/src/components/RunwayLookCard.astro index 740ceee..4cc7dc0 100644 --- a/src/components/RunwayLookCard.astro +++ b/src/components/RunwayLookCard.astro @@ -1,6 +1,9 @@ --- import type { RawArticle } from "@/lib/api" import GalleryLightbox from "@/components/GalleryLightbox.astro" +import DetailCountBadge from "@/components/DetailCountBadge.astro" +import GalleryDetailLightbox from "@/components/GalleryDetailLightbox.astro" +import LbDetailsStrip from "@/components/LbDetailsStrip.astro" import { getI18n } from "@/lib/i18n" import { href, ROUTES } from '@/lib/routes' import { ssrAbs } from "@/lib/request" @@ -171,25 +174,8 @@ const homeHref = href(locale, ROUTES.home) - {/* 细节图数量角标:有细节图的主图在左下角标注「张数」(图层图标 + 数字), - 点它直接开细节灯箱。纯主图(无细节图)不显示任何角标,保持网格干净。 - 数量走 Alpine 的 detailCount()(响应式):未登录取前 PREVIEW_LIMIT 张的细节子树, - 登录后由 gallery:full 重建映射,两态共用同一条渲染路径。 */} - + {/* 细节图数量角标(共享组件):有细节图的主图左下角标「张数」,点它开细节灯箱。 */} + ) })} @@ -255,20 +241,8 @@ const homeHref = href(locale, ROUTES.home) - {/* 细节图数量角标:有细节图的主图左下角标「张数」,点它直接开细节灯箱(与首屏图一致) */} - + {/* 细节图数量角标(共享组件,客户端补拉图,与首屏一致) */} + @@ -302,421 +276,40 @@ const homeHref = href(locale, ROUTES.home) {/* 大图灯箱:与街拍详情共用 components/GalleryLightbox.astro(标记)+ lib/gallery.ts(交互)。 走秀独有的「当前 look 的细节图簇」经 details 插槽注入。 */} {article && previewImages.length > 0 && ( - {/* 当前 look 的细节图:右下角一小簇缩略图(竖版主图右下角本就是空白,不遮挡主图)。 - 主图放大(lbZoomed)时整簇隐藏——放大态要专注当前大图;点其中一张进细节灯箱看大图。 - 单个 look 最多 4 张细节图(多数 1~2 张),一排横放即可,不设滚动条。 */} -
- Details -
- -
-
+ {/* 当前主图的细节图缩略簇(共享组件) */} +
)} - {/* ===== 细节图灯箱:点大图灯箱里的细节缩略图打开,单张细节图放大查看 ===== */} - {article && previewImages.length > 0 && ( - - )} + {/* 细节图灯箱(共享组件):点大图灯箱里的细节缩略图打开,单张细节图放大查看 */} + {article && previewImages.length > 0 && } diff --git a/src/components/StreetSnapCard.astro b/src/components/StreetSnapCard.astro index 4ab360a..9899a00 100644 --- a/src/components/StreetSnapCard.astro +++ b/src/components/StreetSnapCard.astro @@ -1,6 +1,9 @@ --- import type { RawStreetSnap } from "@/lib/api" import GalleryLightbox from "@/components/GalleryLightbox.astro" +import DetailCountBadge from "@/components/DetailCountBadge.astro" +import GalleryDetailLightbox from "@/components/GalleryDetailLightbox.astro" +import LbDetailsStrip from "@/components/LbDetailsStrip.astro" import { getI18n } from "@/lib/i18n" import { href, ROUTES } from '@/lib/routes' import { ssrAbs } from "@/lib/request" @@ -23,6 +26,7 @@ const images = (snap?.images ?? []) thumb: ssrAbs(im.thumb || im.image || ""), raw: im.image || "", // 相对路径:收藏快照存相对地址,不把宿主/端口写死进库 name: im.name || "", + lookIndex: Number(im.look_index ?? 0), })) .filter((im) => im.url) @@ -35,6 +39,12 @@ const previewImages = images.slice(0, PREVIEW_LIMIT) // 已登录(preview=false)或图片本就不超上限时 lockedCount=0,不渲染占位。 const lockedCount = preview ? Math.max(0, (imageTotal || 0) - previewImages.length) : 0 +// 递给浏览器端 Alpine 的副图数据:只序列化「带副图的主图」投影(look_index + detail), +// 供 lib/galleryDetail.ts 构建 look_index → 副图 映射(与登录后完整 images 同构解析)。 +const detailPayload = (snap?.images ?? []) + .filter((im) => (im.detail?.length ?? 0) > 0) + .map((im) => ({ look_index: Number(im.look_index ?? 0), detail: im.detail })) + const homeHref = href(locale, ROUTES.home) // theimpression 标题含字面 \t:地点 \t 场次,列表/详情统一以 " · " 呈现 @@ -49,6 +59,7 @@ const displayTitle = (snap?.title || "").replace(/\t/g, " · ") data-gallery-title={displayTitle} data-gallery-brand="" data-preview={preview ? "true" : "false"} + data-details={JSON.stringify(detailPayload)} class="min-h-screen bg-white text-black font-sans selection:bg-black selection:text-white" > { @@ -67,6 +78,7 @@ const displayTitle = (snap?.title || "").replace(/\t/g, " · ") {previewImages.map((im, i) => (
+ {/* 副图数量角标(共享组件):有副图的主图左下角标「张数」,点它开副图灯箱 */} + + {im.name && (
{im.name} @@ -137,6 +152,7 @@ const displayTitle = (snap?.title || "").replace(/\t/g, " · ")