v1.4 — Photo 详情页画廊

- 灯箱画廊:点击图片全屏查看,多图左右切换
- 单图隐藏左右箭头,边界隐藏对应方向键
- 画廊顶部显示'标题 · 作者'
- 文章导航保留在灯箱底部
- 图片去重(特色图与正文图片不重复)
- 纯黑背景
- 已知限制:画廊内切换文章后灯箱不保持(AJAX 模式未稳定)
This commit is contained in:
2026-05-04 01:44:56 +08:00
parent c615206e88
commit 55cfd26162
4 changed files with 230 additions and 12 deletions
+16 -1
View File
@@ -210,10 +210,25 @@ function kjweji_register_photo() {
),
'public' => true,
'has_archive' => false,
'rewrite' => array('slug' => 'photo'),
'rewrite' => array('slug' => 'photo/%post_id%'),
'show_in_rest' => true,
'supports' => array('title', 'editor', 'author', 'thumbnail'),
'menu_position' => 26,
'menu_icon' => 'dashicons-format-gallery',
));
}
add_filter('post_type_link', function($link, $post) {
if ($post->post_type === 'photo' && $post->post_status === 'publish') {
return home_url(user_trailingslashit('/photo/' . $post->ID . '/' . $post->post_name));
}
return $link;
}, 10, 2);
// 匹配 /photo/123/slug/ 格式
add_action('init', function() {
add_rewrite_rule('^photo/([0-9]+)/([^/]+)/?$', 'index.php?post_type=photo&p=$matches[1]', 'top');
add_rewrite_rule('^photo/([0-9]+)/?$', 'index.php?post_type=photo&p=$matches[1]', 'top');
});
-1
View File
@@ -9,7 +9,6 @@ get_header();
$photo_query = new WP_Query(array(
'post_type' => 'photo',
'posts_per_page' => -1,
'meta_key' => '_thumbnail_id',
));
?>
+133 -10
View File
@@ -1,18 +1,53 @@
<?php get_header(); ?>
<?php while (have_posts()) : the_post(); ?>
<div class="photo-detail">
<?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>
<div class="photo-detail__image">
<?php if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail('medium_large', array('alt' => get_the_title())); ?>
<?php endif; ?>
<?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 (get_the_content()) : ?>
<?php if ($content) : ?>
<div class="photo-detail__body">
<?php the_content(); ?>
<?php
// 图片换成可点击版本
$content = preg_replace('/<img[^>]+src="([^"]+)"[^>]*>/', '<img src="$1" alt="" onclick="event.stopPropagation(); openPhotoImage(\'' . esc_js('$1') . '\')" />', $content);
echo $content;
?>
</div>
<?php endif; ?>
@@ -27,9 +62,8 @@
</div>
<?php
// 拾影列表按日期从新到旧,导航遵循同一方向
$left = get_adjacent_post(false, '', false); // 更新的(列表左侧)
$right = get_adjacent_post(false, '', true); // 更早的(列表右侧)
$left = get_adjacent_post(false, '', false);
$right = get_adjacent_post(false, '', true);
if ($left || $right) : ?>
<div class="photo-detail__nav">
<?php if ($left) : ?>
@@ -45,4 +79,93 @@
</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(); ?>
+81
View File
@@ -407,3 +407,84 @@ echo "done"
border-top: 2px dashed var(--border);
}
.photo-detail__meta { border-top: none; padding-top: 0; }
.photo-detail__body img {
display: block;
width: 100%;
height: auto;
margin: 20px 0;
border-radius: var(--radius);
}
.photo-detail__body p {
margin: 16px 0;
text-align: center;
font-style: italic;
color: var(--ink-light);
}
/* 照片灯箱 */
.photo-lightbox {
display: none;
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: #000;
z-index: 9999;
justify-content: center; align-items: center;
}
.photo-lightbox.active { display: flex; }
.photo-lightbox__content { max-width: 90vw; max-height: 90vh; }
.photo-lightbox__content img { max-width: 90vw; max-height: 85vh; object-fit: contain; border-radius: var(--radius); }
.photo-lightbox__close { position: absolute; top: 24px; right: 36px; font-size: 42px; color: #fff; cursor: pointer; opacity: 0.8; z-index: 2; }
.photo-lightbox__close:hover { opacity: 1; }
.photo-lightbox__counter { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); color: #fff; font-size: 14px; opacity: 0.7; z-index: 2; }
.photo-lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%); font-size: 56px; color: #fff; cursor: pointer; user-select: none; padding: 24px; opacity: 0.7; z-index: 2; }
.photo-lightbox__nav:hover { opacity: 1; }
.photo-lightbox__prev { left: 16px; }
.photo-lightbox__next { right: 16px; }
/* 图片可点击提示 */
.photo-detail__image { cursor: zoom-in; }
.photo-detail__body img { cursor: zoom-in; }
.photo-lightbox__postnav {
position: absolute;
bottom: 18px;
left: 0; right: 0;
display: flex;
justify-content: space-between;
padding: 0 40px;
z-index: 2;
}
.photo-lightbox__postnav a {
color: rgba(255,255,255,0.6);
text-decoration: none;
font-size: 14px;
}
.photo-lightbox__postnav a:hover { color: #fff; }
.photo-lightbox__postnav span { color: transparent; }
.photo-lightbox__counter { bottom: 60px; }
.photo-lightbox__brand {
position: absolute;
top: 24px;
left: 36px;
color: rgba(255,255,255,0.25);
font-size: 16px;
letter-spacing: 0.1em;
z-index: 2;
font-family: "Noto Serif SC", "STSong", "Songti SC", serif;
}
.photo-lightbox__info {
text-align: center;
margin-bottom: 16px;
}
.photo-lightbox__photo-title {
color: rgba(255,255,255,0.5);
font-size: 15px;
font-weight: 400;
letter-spacing: 0.04em;
}
.photo-lightbox__content img { border-radius: 6px; }