Files
kjweiji/single-photo.php
liaoxin 55cfd26162 v1.4 — Photo 详情页画廊
- 灯箱画廊:点击图片全屏查看,多图左右切换
- 单图隐藏左右箭头,边界隐藏对应方向键
- 画廊顶部显示'标题 · 作者'
- 文章导航保留在灯箱底部
- 图片去重(特色图与正文图片不重复)
- 纯黑背景
- 已知限制:画廊内切换文章后灯箱不保持(AJAX 模式未稳定)
2026-05-04 01:44:56 +08:00

172 lines
6.8 KiB
PHP
Raw Permalink 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.
<?php get_header(); ?>
<?php while (have_posts()) : the_post(); ?>
<?php
// 收集所有图片 URL(去重)
$gallery = array();
$seen = array();
// 正文中的图片(先收,因为特色图和正文第一张可能重复)
$content_raw = get_the_content();
if (preg_match_all('/<img[^>]+src="([^"]+)"/', $content_raw, $m)) {
foreach ($m[1] as $url) {
$key = basename(parse_url($url, PHP_URL_PATH));
if (!isset($seen[$key])) {
$seen[$key] = true;
$gallery[] = $url;
}
}
}
// 特色图(如果没有出现在正文中则加入)
if (has_post_thumbnail()) {
$thumb_url = get_the_post_thumbnail_url(null, 'large');
$key = basename(parse_url($thumb_url, PHP_URL_PATH));
if (!isset($seen[$key])) {
$gallery[] = $thumb_url;
}
}
$gallery_json = json_encode($gallery);
$content = $content_raw;
?>
<div class="photo-detail" id="photo-detail"
data-gallery="<?php echo esc_attr($gallery_json); ?>"
data-title="<?php echo esc_attr(get_the_title()); ?>"
data-author="<?php echo esc_attr(get_avatar(get_the_author_meta('ID'), 18) . ' ' . get_the_author_meta('display_name')); ?>">
<a href="/photos/" class="back-link">← 返回拾影</a>
<?php // 多图文章的特色图已在正文中,不重复显示
if (!preg_match('/<img[^>]+src=/', $content) && has_post_thumbnail()) : ?>
<div class="photo-detail__image" onclick="openPhotoGallery(0)">
<?php the_post_thumbnail('medium_large', array('alt' => get_the_title())); ?>
</div>
<?php endif; ?>
<?php if ($content) : ?>
<div class="photo-detail__body">
<?php
// 图片换成可点击版本
$content = preg_replace('/<img[^>]+src="([^"]+)"[^>]*>/', '<img src="$1" alt="" onclick="event.stopPropagation(); openPhotoImage(\'' . esc_js('$1') . '\')" />', $content);
echo $content;
?>
</div>
<?php endif; ?>
<div class="photo-detail__divider"></div>
<h1 class="photo-detail__title"><?php the_title(); ?></h1>
<div class="photo-detail__meta">
<span><?php echo get_avatar(get_the_author_meta('ID'), 18); ?> <?php the_author_meta('display_name'); ?></span>
<span>&middot;</span>
<span><?php echo get_the_date('Y-m-d'); ?></span>
</div>
<?php
$left = get_adjacent_post(false, '', false);
$right = get_adjacent_post(false, '', true);
if ($left || $right) : ?>
<div class="photo-detail__nav">
<?php if ($left) : ?>
<a href="<?php echo get_permalink($left); ?>">← <?php echo get_the_title($left); ?></a>
<?php else: ?>
<span></span>
<?php endif; ?>
<?php if ($right) : ?>
<a href="<?php echo get_permalink($right); ?>"><?php echo get_the_title($right); ?> →</a>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php endwhile; ?>
<!-- 照片灯箱 — 文章导航内联,不跳页面 -->
<div class="photo-lightbox" id="photo-lightbox" onclick="closePhotoLightbox()">
<span class="photo-lightbox__brand"><?php bloginfo('name'); ?></span>
<span class="photo-lightbox__close" onclick="closePhotoLightbox()">&times;</span>
<span class="photo-lightbox__counter" id="photo-lightbox-counter"></span>
<span class="photo-lightbox__nav photo-lightbox__prev" onclick="event.stopPropagation(); navigatePhoto(-1)"></span>
<span class="photo-lightbox__nav photo-lightbox__next" onclick="event.stopPropagation(); navigatePhoto(1)"></span>
<div onclick="event.stopPropagation()">
<div class="photo-lightbox__info" id="photo-lightbox-info"></div>
<div class="photo-lightbox__content">
<img id="photo-lightbox-img" src="" alt="">
</div>
</div>
<div class="photo-lightbox__postnav" id="photo-lightbox-postnav"></div>
</div>
<script>
(function() {
var detail = document.getElementById('photo-detail');
if (!detail) return;
var gallery = JSON.parse(detail.getAttribute('data-gallery') || '[]');
var lb = document.getElementById('photo-lightbox');
var lbImg = document.getElementById('photo-lightbox-img');
var lbCounter = document.getElementById('photo-lightbox-counter');
var idx = 0;
window.openPhotoGallery = function(i) {
idx = i;
show();
updateNavButtons();
updatePhotoInfo();
lb.classList.add('active');
document.body.style.overflow = 'hidden';
showPostNav();
};
function updatePhotoInfo() {
var info = document.getElementById('photo-lightbox-info');
if (!info) return;
var title = detail.getAttribute('data-title') || '';
var author = detail.getAttribute('data-author') || '';
// 提取作者纯文本(去掉 img 标签)
var tmp = document.createElement('div');
tmp.innerHTML = author;
var author_text = tmp.textContent.trim();
info.innerHTML = '<span class="photo-lightbox__photo-title">' + title + ' · ' + author_text + '</span>';
}
window.openPhotoImage = function(url) {
var i = gallery.indexOf(url);
if (i >= 0) openPhotoGallery(i);
else { idx = -1; lbImg.src = url; lbCounter.textContent = ''; lb.classList.add('active'); document.body.style.overflow = 'hidden'; }
};
window.navigatePhoto = function(d) {
idx = (idx + d + gallery.length) % gallery.length;
show();
};
window.closePhotoLightbox = function() {
lb.classList.remove('active');
document.body.style.overflow = '';
};
function showPostNav() {
var nav = document.querySelector('.photo-detail__nav');
var pn = document.getElementById('photo-lightbox-postnav');
if (nav && pn) pn.innerHTML = nav.innerHTML;
}
function show() {
lbImg.src = gallery[idx];
lbCounter.textContent = gallery.length > 1 ? (idx + 1) + ' / ' + gallery.length : '';
updateNavButtons();
}
function updateNavButtons() {
var prev = lb.querySelector('.photo-lightbox__prev');
var next = lb.querySelector('.photo-lightbox__next');
if (gallery.length <= 1) {
prev.style.display = 'none';
next.style.display = 'none';
} else {
prev.style.display = idx > 0 ? '' : 'none';
next.style.display = idx < gallery.length - 1 ? '' : 'none';
}
}
document.addEventListener('keydown', function(e) {
if (!lb.classList.contains('active')) return;
if (e.key === 'ArrowLeft') navigatePhoto(-1);
if (e.key === 'ArrowRight') navigatePhoto(1);
if (e.key === 'Escape') closePhotoLightbox();
});
})();
</script>
<?php get_footer(); ?>