diff --git a/README.md b/README.md index b21c171..c26cccd 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,9 @@ - 导航为下拉菜单,自动高亮当前页;顶部始终显示当前用户头像与用户名。 - **点导航栏左上角的「🎬 电影日志」即可回到首页**(右键 / Ctrl+点击还能在新标签页打开),不必再展开右侧折叠菜单去找「首页」。 - 登录页为深色渐变 + 毛玻璃风格。 +- **详情页图片用本页灯箱查看**:海报、票根、观影照片串成一个序列,点任一张即在当前页弹出(不再 `window.open` 到新窗口),**左右箭头翻看并循环**,底部显示「3 / 8」进度与图片说明。 + 可按 **← / →** 翻页、**Esc** 关闭、点画面空白处关闭,手机上还能**左右滑动**切换;弹出时锁定背景滚动,并从相邻位置预取下一张,翻页不白屏。 + 只有一张图时不显示左右箭头;关闭后焦点会回到原来点开的那张图上。 --- diff --git a/detail.php b/detail.php index 404e488..0dc3768 100644 --- a/detail.php +++ b/detail.php @@ -19,6 +19,57 @@ if (!$movie) { } $admin = getCurrentAdmin(); + +// ---------- 灯箱图片序列:海报 → 票根 → 观影照片 ---------- +// 以前每张图都是用 JS 的 window.open 弹到新窗口,没有关闭按钮、体验很差。 +// 现在把所有图片收进这一个序列:点任意一张都在当前页弹出查看, +// 可以左右翻着看票根、合影等,Esc / 点空白处关闭。 +// 这里一次性组装,英雄区海报与下方图库共用同一套下标。 +$gallery = []; +$heroIndex = -1; // 海报在序列里的下标(没有真实海报时不点亮英雄区) +$ticketIndex = -1; +$photoIndexes = []; + +$posterUrl = posterUrl($movie['poster_path']); +$hasRealPoster = ($posterUrl !== '' && strpos($posterUrl, 'placeholder') === false); +if ($hasRealPoster) { + $gallery[] = [ + 'url' => $posterUrl, + 'label' => '🖼️ 海报', + 'caption' => '电影海报 · ' . $movie['title'], + ]; + $heroIndex = 0; +} + +$hasTicket = storageExists($movie['ticket_path'] ?? ''); +if ($hasTicket) { + $gallery[] = [ + 'url' => storageUrl($movie['ticket_path']), + 'label' => '🎫 电影票', + 'caption' => '电影票根 · ' . $movie['title'], + ]; + $ticketIndex = count($gallery) - 1; +} + +// 观影照片:旧字段 photo_path(历史单张)+ movie_photos(多张) +$all_photos = []; +if (storageExists($movie['photo_path'] ?? '')) { + $all_photos[] = ['path' => $movie['photo_path'], 'label' => '📸 旧照片']; +} +foreach ($movie['photos'] as $p) { + if (storageExists($p['photo_path'] ?? '')) { + $all_photos[] = ['path' => $p['photo_path'], 'label' => '📸 观影照片']; + } +} +foreach ($all_photos as $photo) { + $gallery[] = [ + 'url' => storageUrl($photo['path']), + 'label' => $photo['label'], + 'caption' => $photo['label'] . ' · ' . $movie['title'], + ]; + $photoIndexes[] = count($gallery) - 1; +} +$hasGallery = !empty($gallery); ?> @@ -234,6 +285,120 @@ $admin = getCurrentAdmin(); border-left: 4px solid var(--primary); margin-top: 8px; } + + /* ---------- 图片灯箱(替代原来的 window.open 弹窗) ---------- + z-index 要压过导航栏(导航栏是 100),这里用 300。 */ + .lb-openable { + cursor: zoom-in; + } + .lb-openable:focus-visible { + outline: 2px solid var(--primary); + outline-offset: 2px; + } + .lightbox { + position: fixed; + inset: 0; + z-index: 300; + display: none; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.88); + backdrop-filter: blur(4px); + /* 打开时不给滚动条留闪烁空间 */ + overscroll-behavior: contain; + } + .lightbox.open { + display: flex; + } + .lb-stage { + display: flex; + align-items: center; + justify-content: center; + max-width: 92vw; + max-height: 82vh; + } + .lb-img { + max-width: 92vw; + max-height: 78vh; + width: auto; + height: auto; + object-fit: contain; + border-radius: 8px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); + background: transparent; + user-select: none; + -webkit-user-drag: none; + } + .lb-btn { + position: absolute; + border: none; + cursor: pointer; + color: #fff; + background: rgba(255, 255, 255, 0.12); + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.2s ease; + font-family: inherit; + } + .lb-btn:hover { + background: rgba(255, 255, 255, 0.26); + } + .lb-btn:focus-visible { + outline: 2px solid var(--primary); + outline-offset: 2px; + } + /* 只有一张图时 JS 会加 hidden;但作者样式 display:flex 优先级高于 + UA 的 [hidden]{display:none},必须显式写这条才能真正隐藏箭头。 */ + .lb-btn[hidden] { + display: none; + } + .lb-close { + top: 14px; + right: 16px; + width: 40px; + height: 40px; + border-radius: 50%; + font-size: 18px; + line-height: 1; + } + .lb-nav { + top: 50%; + transform: translateY(-50%); + width: 48px; + height: 48px; + border-radius: 50%; + font-size: 28px; + line-height: 1; + padding-bottom: 4px; /* 让箭头符号视觉上居中 */ + } + .lb-prev { left: 14px; } + .lb-next { right: 14px; } + .lb-bar { + position: absolute; + left: 0; + right: 0; + bottom: 0; + padding: 14px 20px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + color: #fff; + font-size: 14px; + background: linear-gradient(to top, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0)); + } + .lb-caption { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .lb-counter { + flex: 0 0 auto; + opacity: 0.75; + font-variant-numeric: tabular-nums; + } + .lb-open { overflow: hidden; } /* 给
加,弹出时锁背景滚动 */ @media (max-width: 768px) { .detail-hero { grid-template-columns: 1fr; @@ -260,6 +425,22 @@ $admin = getCurrentAdmin(); .detail-info h1 { font-size: 22px; } + /* 手机上手指够得到:箭头缩小位置也内收一点,给图片留出更多宽度 */ + .lb-nav { + width: 40px; + height: 40px; + font-size: 24px; + } + .lb-prev { left: 6px; } + .lb-next { right: 6px; } + .lb-img { + max-width: 88vw; + max-height: 70vh; + } + .lb-bar { + padding: 10px 14px; + font-size: 13px; + } } @@ -272,17 +453,19 @@ $admin = getCurrentAdmin();