Merge pull request 'feat: deepen single post experience' (#314) from worktree-frontend-single-deep-rebuild into main

Reviewed-on: CYL/wordpress-theme-aksrt#314
This commit is contained in:
2026-07-28 02:10:12 +08:00
8 changed files with 265 additions and 81 deletions
@@ -1,4 +1,4 @@
/* ========== 浠g爜鍧?GitHub 椋庢牸 ========== */
/* ========== 代码块:GitHub 风格 ========== */
.code-block {
border-radius: var(--radius-code);
border: 1px solid var(--color-line);
@@ -52,8 +52,8 @@
}
}
.entry-content pre.wp-block-code,
.entry-content pre:not(.wp-block-preformatted) {
:is(.entry-content, .wp-posts-content) pre.wp-block-code,
:is(.entry-content, .wp-posts-content) pre:not(.wp-block-preformatted) {
border-radius: var(--radius-code);
border: 1px solid var(--color-line);
background: var(--surface-3);
@@ -61,7 +61,7 @@
overflow: hidden;
}
.entry-content pre code {
:is(.entry-content, .wp-posts-content) pre code {
display: block;
padding: 16px 20px;
overflow-x: auto;
+40 -16
View File
@@ -129,27 +129,33 @@ article.article.box-body,
height: 2px;
}
.entry-content > *:first-child {
:is(.entry-content, .wp-posts-content) > *:first-child {
margin-top: 0;
}
.entry-content p {
:is(.entry-content, .wp-posts-content) p {
margin: 0 0 1.5em;
}
.entry-content h2 {
:is(.entry-content, .wp-posts-content) h2 {
font-size: 20px;
font-weight: 700;
margin: 20px 0 10px;
margin: 28px 0 14px;
}
.entry-content h3 {
:is(.entry-content, .wp-posts-content) h3 {
font-size: 18px;
font-weight: 700;
margin: 20px 0 10px;
margin: 24px 0 12px;
}
.entry-content blockquote {
:is(.entry-content, .wp-posts-content) h4 {
font-size: 16px;
font-weight: 700;
margin: 22px 0 10px;
}
:is(.entry-content, .wp-posts-content) blockquote {
margin: 0 0 24px;
padding: 18px 20px;
border-left: 4px solid var(--color-primary);
@@ -158,11 +164,29 @@ article.article.box-body,
color: var(--color-ink-3);
}
.entry-content img {
:is(.entry-content, .wp-posts-content) img {
margin: 0 auto;
display: block;
max-width: 100%;
height: auto;
border-radius: min(8px, var(--main-radius, 8px));
}
:is(.entry-content, .wp-posts-content) figure {
max-width: 100%;
margin: 1.5em auto;
}
:is(.entry-content, .wp-posts-content) figcaption {
margin-top: 8px;
color: var(--muted-color, #777);
font-size: 13px;
line-height: 1.6;
text-align: center;
}
:is(.entry-content, .wp-posts-content) .aksrt-lightbox-target {
cursor: zoom-in;
}
/* ===== 图片灯箱 ===== */
@@ -226,14 +250,14 @@ article.article.box-body,
pointer-events: none;
}
.entry-content iframe,
.entry-content .wp-block-embed iframe,
.entry-content video {
:is(.entry-content, .wp-posts-content) iframe,
:is(.entry-content, .wp-posts-content) .wp-block-embed iframe,
:is(.entry-content, .wp-posts-content) video {
max-width: 100%;
height: auto;
}
.entry-content .wp-block-embed {
:is(.entry-content, .wp-posts-content) .wp-block-embed {
position: relative;
width: 100%;
max-width: 100%;
@@ -242,7 +266,7 @@ article.article.box-body,
}
/* 行内代码 — 对齐 zibll: 粉色文字 + 粉色背景 */
.entry-content code {
:is(.entry-content, .wp-posts-content) code {
font-family: var(--font-mono);
font-size: 0.9em;
color: #ff3c98;
@@ -251,13 +275,13 @@ article.article.box-body,
border-radius: 4px;
}
.entry-content ul,
.entry-content ol {
:is(.entry-content, .wp-posts-content) ul,
:is(.entry-content, .wp-posts-content) ol {
padding-left: 1.5em;
margin: 0 0 1.5em;
}
.entry-content ul li::marker {
:is(.entry-content, .wp-posts-content) ul li::marker {
color: var(--color-primary);
}
+69
View File
@@ -40,3 +40,72 @@ body.single .sidebar .widget {
body.single main.container {
box-sizing: border-box;
}
/* Reading facts below the author row. */
.article-reading-meta {
display: flex;
flex-wrap: wrap;
gap: 8px 14px;
margin: 12px 0 2px;
color: var(--muted-color, #777);
font-size: 12px;
}
.article-reading-meta span {
display: inline-flex;
align-items: center;
gap: 5px;
}
/* Useful fallback for sites that enable the column before adding widgets. */
.single-overview-widget {
padding: 18px;
border-radius: var(--main-radius, 8px);
background: var(--main-bg-color, #fff);
box-shadow: 0 0 10px var(--main-shadow, rgba(116, 116, 116, 0.08));
}
.single-overview-widget__title {
display: flex;
align-items: center;
gap: 8px;
margin: 0 0 12px;
font-size: 15px;
}
.single-overview-widget__title i {
color: var(--focus-color, #f04494);
}
.single-overview-widget__list {
margin: 0;
}
.single-overview-widget__list > div {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 8px 0;
border-bottom: 1px dashed var(--main-border-color, rgba(50, 50, 50, 0.08));
}
.single-overview-widget__list > div:last-child {
padding-bottom: 0;
border-bottom: 0;
}
.single-overview-widget__list dt,
.single-overview-widget__list dd {
margin: 0;
font-size: 12px;
}
.single-overview-widget__list dt {
color: var(--muted-color, #777);
}
.single-overview-widget__list dd {
color: var(--key-color, #333);
text-align: right;
}
+17 -10
View File
@@ -177,7 +177,7 @@
function initLightbox() {
var overlay = document.getElementById('lightbox-overlay');
var content = document.querySelector(".entry-content[data-aksrt-lightbox='1']");
var content = document.querySelector(".wp-posts-content[data-aksrt-lightbox='1'], .entry-content[data-aksrt-lightbox='1']");
if (!overlay || !content || overlay.dataset.aksrtLightboxBound === '1') return;
overlay.dataset.aksrtLightboxBound = '1';
@@ -188,6 +188,7 @@
function close() {
overlay.classList.remove('is-open');
overlay.setAttribute('aria-hidden', 'true');
document.body.style.overflow = '';
if (image) {
image.src = '';
@@ -196,11 +197,19 @@
}
content.querySelectorAll('img').forEach(function (img) {
img.style.cursor = 'zoom-in';
img.addEventListener('click', function () {
if (!image) return;
var link = img.closest('a[href]');
var linkHref = link ? link.href : '';
var linksToImage = /\.(?:avif|gif|jpe?g|png|svg|webp)(?:[?#].*)?$/i.test(linkHref);
if (img.closest('[data-no-lightbox]') || (link && !linksToImage)) return;
image.src = img.src;
img.classList.add('aksrt-lightbox-target');
img.addEventListener('click', function (event) {
if (!image) return;
if (linksToImage) event.preventDefault();
image.src = linksToImage
? linkHref
: (img.getAttribute('data-src') || img.getAttribute('data-lazy-src') || img.currentSrc || img.src);
image.alt = img.alt || '';
if (caption) {
@@ -210,20 +219,18 @@
}
overlay.classList.add('is-open');
overlay.setAttribute('aria-hidden', 'false');
document.body.style.overflow = 'hidden';
if (closeBtn) closeBtn.focus();
});
});
overlay.addEventListener('click', function (event) {
if (event.target === overlay || event.target === closeBtn) {
if (event.target === overlay || event.target === closeBtn || (event.target.closest && event.target.closest('.lightbox-close'))) {
close();
}
});
if (closeBtn) {
closeBtn.addEventListener('click', close);
}
document.addEventListener('keydown', function (event) {
if (event.key === 'Escape' && overlay.classList.contains('is-open')) {
close();
+1
View File
@@ -29,6 +29,7 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-single-components.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-single.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-yiyan.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-single-render.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-single-aside.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-archive.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-archive-filters.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-comments.php';
+91
View File
@@ -0,0 +1,91 @@
<?php
/**
* Single-post sidebar composition.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_single_render_overview_widget')) :
/**
* Render a useful fallback when no article sidebar widgets are configured.
*
* @param array<string,mixed> $ctx Single context.
*/
function aksrt_single_render_overview_widget(array $ctx): void {
$post_id = (int) ($ctx['post_id'] ?? get_the_ID());
$categories = get_the_category($post_id);
$primary_category = !empty($categories) && $categories[0] instanceof WP_Term ? $categories[0] : null;
$modified = get_the_modified_date('', $post_id);
$overview_items = is_array($ctx['meta_items_secondary'] ?? null) ? $ctx['meta_items_secondary'] : [];
?>
<section class="zib-widget single-overview-widget" aria-labelledby="single-overview-title">
<h3 id="single-overview-title" class="single-overview-widget__title">
<i class="far fa-file-alt" aria-hidden="true"></i>
<?php esc_html_e('文章概览', 'aksrt'); ?>
</h3>
<dl class="single-overview-widget__list">
<?php if ($primary_category instanceof WP_Term) : ?>
<div><dt><?php esc_html_e('分类', 'aksrt'); ?></dt><dd><a href="<?php echo esc_url(get_category_link($primary_category)); ?>"><?php echo esc_html($primary_category->name); ?></a></dd></div>
<?php endif; ?>
<div><dt><?php esc_html_e('浏览', 'aksrt'); ?></dt><dd><?php echo esc_html(number_format_i18n((int) ($ctx['views'] ?? 0))); ?></dd></div>
<div><dt><?php esc_html_e('评论', 'aksrt'); ?></dt><dd><a href="<?php echo esc_url(get_comments_link($post_id)); ?>"><?php echo esc_html(number_format_i18n((int) ($ctx['comment_count'] ?? 0))); ?></a></dd></div>
<?php foreach ($overview_items as $item) : ?>
<?php if (is_array($item) && !empty($item['text'])) : ?>
<div><dt><i class="<?php echo esc_attr((string) ($item['icon'] ?? 'far fa-circle')); ?>" aria-hidden="true"></i></dt><dd><?php echo esc_html((string) $item['text']); ?></dd></div>
<?php endif; ?>
<?php endforeach; ?>
<?php if ($modified !== '') : ?>
<div><dt><?php esc_html_e('更新', 'aksrt'); ?></dt><dd><?php echo esc_html($modified); ?></dd></div>
<?php endif; ?>
</dl>
</section>
<?php
}
endif;
if (!function_exists('aksrt_single_render_aside')) :
/**
* Render the page-owned single sidebar.
*
* @param array<string,mixed> $ctx Single context.
*/
function aksrt_single_render_aside(array $ctx): void {
if (empty($ctx['show_aside']) || wp_is_mobile()) {
return;
}
$has_article_widgets = is_active_sidebar('all_sidebar_top')
|| is_active_sidebar('sidebar-article')
|| is_active_sidebar('all_sidebar_bottom');
?>
<div class="sidebar" role="complementary" aria-label="<?php esc_attr_e('侧栏', 'aksrt'); ?>">
<?php if (!empty($ctx['has_download'])) : ?>
<?php get_template_part('templates/parts/resource-meta-box'); ?>
<?php endif; ?>
<?php if (!$has_article_widgets) : ?>
<?php aksrt_single_render_overview_widget($ctx); ?>
<?php endif; ?>
<?php if (!empty($ctx['show_toc'])) : ?>
<div class="zib-widget toc-widget posts-nav-box" data-title="<?php echo esc_attr((string) ($ctx['toc_title'] ?? __('文章目录', 'aksrt'))); ?>">
<h3><?php echo esc_html((string) ($ctx['toc_title'] ?? __('文章目录', 'aksrt'))); ?></h3>
<ol class="toc-list"></ol>
</div>
<?php endif; ?>
<?php if (is_active_sidebar('all_sidebar_top')) : ?>
<?php dynamic_sidebar('all_sidebar_top'); ?>
<?php endif; ?>
<?php if (is_active_sidebar('sidebar-article')) : ?>
<?php dynamic_sidebar('sidebar-article'); ?>
<?php endif; ?>
<?php if (is_active_sidebar('all_sidebar_bottom')) : ?>
<?php dynamic_sidebar('all_sidebar_bottom'); ?>
<?php endif; ?>
</div>
<?php
}
endif;
+35 -44
View File
@@ -176,6 +176,15 @@ if (!function_exists('aksrt_single_render_box_header')) :
'show_time' => empty($settings['hide_time']),
'meta_html' => empty($ctx['show_cover']) ? (string) ($ctx['meta_box_html'] ?? '') : '',
]);
$reading_meta = is_array($ctx['meta_items_secondary'] ?? null) ? $ctx['meta_items_secondary'] : [];
if ($reading_meta !== []) :
?>
<div class="article-reading-meta" aria-label="<?php esc_attr_e('阅读信息', 'aksrt'); ?>">
<?php foreach ($reading_meta as $item) : ?>
<span><i class="<?php echo esc_attr((string) ($item['icon'] ?? 'far fa-file-alt')); ?>" aria-hidden="true"></i><?php echo esc_html((string) ($item['text'] ?? '')); ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
?>
</div>
<?php
@@ -389,9 +398,19 @@ if (!function_exists('aksrt_single_render_author_card')) :
$q['post__not_in'] = [(int) $cur];
}
if ($card_orderby === 'views') {
$q['meta_key'] = 'views';
$q['orderby'] = 'meta_value_num';
$q['order'] = 'DESC';
$q['meta_query'] = [
'relation' => 'OR',
'views_value' => [
'key' => 'aksrt_post_views',
'compare' => 'EXISTS',
'type' => 'NUMERIC',
],
'views_missing' => [
'key' => 'aksrt_post_views',
'compare' => 'NOT EXISTS',
],
];
$q['orderby'] = ['views_value' => 'DESC', 'date' => 'DESC'];
} elseif ($card_orderby === 'comment_count') {
$q['orderby'] = 'comment_count';
$q['order'] = 'DESC';
@@ -657,8 +676,19 @@ if (!function_exists('aksrt_single_related_query_args')) :
$args['orderby'] = 'modified';
break;
case 'views':
$args['meta_key'] = 'aksrt_post_views';
$args['orderby'] = 'meta_value_num';
$args['meta_query'] = [
'relation' => 'OR',
'views_value' => [
'key' => 'aksrt_post_views',
'compare' => 'EXISTS',
'type' => 'NUMERIC',
],
'views_missing' => [
'key' => 'aksrt_post_views',
'compare' => 'NOT EXISTS',
],
];
$args['orderby'] = ['views_value' => 'DESC', 'date' => 'DESC'];
break;
case 'relevance':
default:
@@ -938,42 +968,3 @@ if (!function_exists('aksrt_single_render_after_box')) :
}
endif;
if (!function_exists('aksrt_single_render_aside')) :
/**
* Page-owned single aside (not a generic sidebar prepend hack).
*
* @param array<string,mixed> $ctx Single context.
*/
function aksrt_single_render_aside(array $ctx): void {
if (empty($ctx['show_aside']) || wp_is_mobile()) {
return;
}
?>
<div class="sidebar" role="complementary" aria-label="<?php esc_attr_e('侧栏', 'aksrt'); ?>">
<?php if (!empty($ctx['has_download'])) : ?>
<?php get_template_part('templates/parts/resource-meta-box'); ?>
<?php endif; ?>
<?php if (!empty($ctx['show_toc'])) : ?>
<div class="zib-widget toc-widget posts-nav-box" data-title="<?php echo esc_attr((string) $ctx['toc_title']); ?>">
<h3><?php echo esc_html((string) $ctx['toc_title']); ?></h3>
<ol class="toc-list"></ol>
</div>
<?php endif; ?>
<?php if (is_active_sidebar('all_sidebar_top')) : ?>
<?php dynamic_sidebar('all_sidebar_top'); ?>
<?php endif; ?>
<?php if (is_active_sidebar('sidebar-article')) : ?>
<?php dynamic_sidebar('sidebar-article'); ?>
<?php endif; ?>
<?php if (is_active_sidebar('all_sidebar_bottom')) : ?>
<?php dynamic_sidebar('all_sidebar_bottom'); ?>
<?php endif; ?>
</div>
<?php
}
endif;
+8 -7
View File
@@ -73,13 +73,6 @@ while (have_posts()) :
?>
</main>
<?php if (function_exists('dynamic_sidebar')) : ?>
<div class="fluid-widget-wrap">
<?php dynamic_sidebar('single_bottom_fluid'); ?>
<?php dynamic_sidebar('all_bottom_fluid'); ?>
</div>
<?php endif; ?>
<?php if (!empty($ctx['show_toc'])) : ?>
<button type="button" class="toc-float-btn" aria-label="<?php esc_attr_e('打开目录', 'aksrt'); ?>"><i class="fas fa-list-ul" aria-hidden="true"></i></button>
<div class="toc-drawer-overlay"></div>
@@ -92,6 +85,14 @@ while (have_posts()) :
</aside>
<?php endif; ?>
<?php if (!empty($settings['lightbox'])) : ?>
<div class="lightbox-overlay" id="lightbox-overlay" role="dialog" aria-modal="true" aria-label="<?php esc_attr_e('图片预览', 'aksrt'); ?>" aria-hidden="true">
<button type="button" class="lightbox-close" aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>"><i class="fas fa-times" aria-hidden="true"></i></button>
<img src="" alt="" class="lightbox-img">
<div class="lightbox-caption" aria-live="polite"></div>
</div>
<?php endif; ?>
<?php endwhile; ?>
<?php get_footer(); ?>