feat(pages): 1:1 文档导航 + 文章归档 (zibll documentnav/archives)

Category accordion + AJAX cat/search posts for documentnav; archives
month lists with view/comment/like meta, sidebar and comments shell.
This commit is contained in:
kate522 committed 2026-07-18 21:54:02 +08:00
1 parent 7dc0d0e92a
commit 7bf0bc81b7
9 files changed
+1072 -207

No files matched your search

+98 -58
View File
@@ -1,9 +1,10 @@
<?php
/**
* Template Name: AKSRT - Archives
* Template Name: AKSRT - 文章归档
* Template Post Type: page
*
* 文章归档页:按年月分组展示全站文章。
* Zibll pages/archives.php 1:1 — month groups with view/comment/like meta,
* theme-box shell, sidebar + comments.
*
* @package AKSRT
*/
@@ -11,65 +12,104 @@
defined('ABSPATH') || exit;
get_header();
global $wpdb;
if (function_exists('aksrt_archive_open_shell')) {
aksrt_archive_open_shell([
'main_class' => 'site-main container content-shell content-shell--page page-content-default',
'has_sidebar' => false,
'page_kind' => 'archives',
]);
}
$header_style = (string) get_post_meta(get_queried_object_id(), 'page_header_style', true);
?>
<div class="content-main content-main--page content-main--archives">
<?php
get_template_part('templates/parts/page-header', null, [
'title' => esc_html__('文章归档', 'aksrt'),
]);
?>
<main class="container page-template-archives">
<div class="content-wrap">
<div class="content-layout">
<?php if ($header_style !== '1' && $header_style !== 'not') : ?>
<div class="theme-box radius8 main-bg main-shadow box-body mb20">
<h1 class="article-title"><?php echo esc_html(get_the_title() ?: __('文章归档', 'aksrt')); ?></h1>
</div>
<?php endif; ?>
<div class="aksrt-archives">
<?php
$years = $wpdb->get_results(
"SELECT DISTINCT YEAR(post_date) AS year, MONTH(post_date) AS month, COUNT(*) AS count
FROM {$wpdb->posts}
WHERE post_type = 'post' AND post_status = 'publish'
GROUP BY YEAR(post_date), MONTH(post_date)
ORDER BY year DESC, month DESC"
); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
$current_year = 0;
foreach ($years as $row) :
if ((int) $row->year !== $current_year) :
$current_year = (int) $row->year;
?>
<h2 class="aksrt-archives__year"><?php echo esc_html((string) $current_year); ?></h2>
<?php endif; ?>
<h3 class="aksrt-archives__month">
<?php echo esc_html(sprintf('%d 月 (%d 篇)', (int) $row->month, (int) $row->count)); ?>
</h3>
<ul class="aksrt-archives__list">
<?php
$month_posts = get_posts([
'year' => (int) $row->year,
'monthnum' => (int) $row->month,
'posts_per_page' => -1,
'post_status' => 'publish',
]);
foreach ($month_posts as $mp) :
?>
<li class="aksrt-archives__item">
<span class="aksrt-archives__date"><?php echo esc_html(get_the_date('m-d', $mp)); ?></span>
<a href="<?php echo esc_url(get_permalink($mp->ID)); ?>" class="aksrt-archives__link"><?php echo esc_html($mp->post_title); ?></a>
</li>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
</div>
<div class="theme-box radius8 main-bg main-shadow">
<?php if ($header_style === '1') : ?>
<div class="box-body">
<h1 class="article-title"><?php echo esc_html(get_the_title() ?: __('文章归档', 'aksrt')); ?></h1>
</div>
<?php
if (function_exists('aksrt_archive_close_shell')) {
aksrt_archive_close_shell(['has_sidebar' => false]);
}
<?php endif; ?>
<article class="box-body">
<?php
$previous_year = 0;
$previous_month = 0;
$ul_open = false;
$myposts = get_posts([
'numberposts' => -1,
'orderby' => 'date',
'order' => 'DESC',
'post_status' => 'publish',
'post_type' => 'post',
'suppress_filters' => false,
]);
foreach ($myposts as $post) :
setup_postdata($post);
$year = (int) get_the_time('Y', $post);
$month = (int) get_the_time('n', $post);
$day = (int) get_the_time('j', $post);
if ($year !== $previous_year || $month !== $previous_month) :
if ($ul_open) {
echo '</ul></div>';
}
echo '<div class="zib-widget mb20"><h4 class="text-center title-h-center">';
echo esc_html(get_the_time('Y年n月', $post));
echo '</h4><ul class="list-inline archives-month-list">';
$ul_open = true;
$previous_year = $year;
$previous_month = $month;
endif;
$views = function_exists('aksrt_get_post_views') ? (int) aksrt_get_post_views($post->ID) : 0;
$likes = (int) get_post_meta($post->ID, 'like', true);
if ($likes <= 0) {
$likes = (int) get_post_meta($post->ID, 'aksrt_like', true);
}
$comments = (int) get_comments_number($post->ID);
?>
<li class="author-set-left muted-color">
<time datetime="<?php echo esc_attr(get_the_date('c', $post)); ?>"><?php echo esc_html((string) $day); ?><?php esc_html_e('日', 'aksrt'); ?></time>
</li>
<li class="author-set-right">
<a href="<?php echo esc_url(get_permalink($post)); ?>"><?php echo esc_html(get_the_title($post)); ?></a>
<span class="muted-2-color ml6" title="<?php esc_attr_e('阅读', 'aksrt'); ?>">
<i class="fa fa-eye" aria-hidden="true"></i><?php echo esc_html((string) $views); ?>
</span>
<?php if ($comments > 0) : ?>
<span class="muted-2-color ml6" title="<?php esc_attr_e('评论', 'aksrt'); ?>">
<i class="fa fa-comment-o" aria-hidden="true"></i><?php echo esc_html((string) $comments); ?>
</span>
<?php endif; ?>
<?php if ($likes > 0) : ?>
<span class="muted-2-color ml6" title="<?php esc_attr_e('点赞', 'aksrt'); ?>">
<i class="fa fa-thumbs-o-up" aria-hidden="true"></i><?php echo esc_html((string) $likes); ?>
</span>
<?php endif; ?>
</li>
<?php
endforeach;
wp_reset_postdata();
if ($ul_open) {
echo '</ul></div>';
}
if (empty($myposts)) {
echo '<p class="muted-2-color text-center">' . esc_html__('暂无文章', 'aksrt') . '</p>';
}
?>
</article>
</div>
<?php
if (comments_open() || get_comments_number()) {
comments_template();
}
?>
</div>
</div>
<?php get_sidebar(); ?>
</main>
<?php
get_footer();
+98 -149
View File
@@ -1,167 +1,116 @@
<?php
/**
* Template Name: AKSRT - Document Navigation
* Template Name: AKSRT - 文档导航
* Template Post Type: page
*
* 文档导航页:文档站式导航。
* 支持侧边章节树、当前章节高亮、索引卡片、最近更新列表、基础搜索。
* Zibll pages/documentnav.php 1:1 — category accordion + search + AJAX posts.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
use AKSRT\Core\DocumentNav;
$post_id = (int) get_queried_object_id();
$opt = class_exists(DocumentNav::class)
? DocumentNav::get_options($post_id)
: ['cat' => 0, 'initial_content' => 'updated_posts'];
$one_cat = (int) ($opt['cat'] ?? 0);
$initial = (string) ($opt['initial_content'] ?? 'updated_posts');
get_header();
// Read doc mode settings
$doc_settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_docs_mode_settings() : [];
$default_order = $doc_settings['default_order'] ?? 'menu_order';
$presenter = class_exists('\AKSRT\Core\DocsPresenter') ? \AKSRT\Core\DocsPresenter::get_instance() : null;
// Get root-level pages
$pages = $presenter
? $presenter->get_root_pages($default_order)
: get_pages([
'sort_column' => $default_order === 'title' ? 'post_title' : ($default_order === 'date' ? 'post_date' : 'menu_order, post_title'),
'sort_order' => 'ASC',
'parent' => 0,
'hierarchical' => 0,
'post_status' => 'publish',
]);
// Recent updates
$recent_pages = $presenter
? $presenter->get_recent_pages(8)
: get_pages([
'sort_column' => 'post_modified',
'sort_order' => 'DESC',
'number' => 8,
'post_status' => 'publish',
]);
$show_sidebar = !empty($doc_settings['toc_enabled']) || !empty($recent_pages);
?>
<main class="container page-template-documentnav">
<div class="content-wrap">
<div class="content-layout">
<div class="theme-box radius8 main-bg main-shadow box-body mb20">
<h1 class="article-title"><?php echo esc_html(get_the_title() ?: __('文档导航', 'aksrt')); ?></h1>
</div>
<main id="main-content" class="container page-content-default" tabindex="-1">
<div class="row document-nav-row">
<div class="col-sm-4 document-nav-aside">
<div class="theme-box zib-widget dosc-nav document-nav">
<?php
if ($one_cat > 0 && class_exists(DocumentNav::class)) {
$open = true;
echo DocumentNav::render_panels($one_cat, 'accordion', 'panel', $open); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} elseif (current_user_can('edit_pages')) {
echo '<p class="muted-2-color box-body">' . esc_html__('请在页面设置中选择一级分类。', 'aksrt') . '</p>';
} else {
echo '<p class="muted-2-color box-body">' . esc_html__('暂无文档分类', 'aksrt') . '</p>';
}
?>
</div>
</div>
<div class="col-sm-8 document-nav-main" role="main">
<div class="theme-box zib-widget document-search relative-h">
<form class="document-search-form" action="javascript:;" method="get">
<div class="line-form">
<input type="search" name="s" class="line-form-input document-search-input" placeholder="<?php esc_attr_e('搜索文档…', 'aksrt'); ?>" autocomplete="off" required minlength="2">
<button type="submit" class="abs-right null" aria-label="<?php esc_attr_e('搜索', 'aksrt'); ?>">
<i class="fa fa-search" aria-hidden="true"></i>
</button>
</div>
</form>
<div class="history-search mt10">
<div>
<?php
if (class_exists(DocumentNav::class)) {
echo DocumentNav::get_instance()->history_buttons_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
</div>
</div>
<div class="search-loading absolute main-bg flex jc" hidden>
<i class="loading mr10 em12" aria-hidden="true"></i> <?php esc_html_e('正在搜索', 'aksrt'); ?>
</div>
</div>
<header class="aksrt-doc-nav-header">
<h1 class="aksrt-doc-nav-header__title"><?php echo esc_html(get_the_title() ?: __('文档导航', 'aksrt')); ?></h1>
<?php $desc = get_the_excerpt(); if ($desc) : ?>
<p class="aksrt-doc-nav-header__desc"><?php echo esc_html($desc); ?></p>
<?php endif; ?>
</header>
<div class="document-nav-container" data-one-cat="<?php echo (int) $one_cat; ?>">
<?php
if ($initial === 'page_content') {
while (have_posts()) {
the_post();
echo '<div class="nopw-sm box-body theme-box radius8 main-bg main-shadow">';
echo '<article class="article wp-posts-content">';
the_content();
echo '</article></div>';
}
} elseif ($one_cat > 0 && class_exists(DocumentNav::class)) {
$args = [
'cat' => $one_cat,
'order' => 'DESC',
'orderby' => 'modified',
'posts_per_page' => 12,
'no_found_rows' => true,
'ignore_sticky_posts' => true,
'post_status' => 'publish',
];
if ($initial === 'date_posts') {
$args['orderby'] = 'date';
} elseif ($initial === 'views_posts') {
$args['orderby'] = 'meta_value_num';
$args['meta_key'] = 'aksrt_post_views';
}
$q = new WP_Query($args);
echo DocumentNav::render_posts_html($q); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
echo '<div class="zib-widget"><p class="muted-2-color text-center">' . esc_html__('请配置文档分类', 'aksrt') . '</p></div>';
}
?>
</div>
</div>
</div>
<div class="aksrt-doc-nav container" data-aksrt-doc-page-id="<?php echo (int) get_the_ID(); ?>">
<div class="content-wrap">
<div class="content-layout<?php echo $show_sidebar && !empty($recent_pages) ? '' : ' content-layout--no-sidebar'; ?>">
<div class="content-layout__primary">
<!-- Quick search -->
<div class="aksrt-doc-nav__search">
<input type="text" class="aksrt-doc-nav__search-input" placeholder="<?php esc_attr_e('搜索文档...', 'aksrt'); ?>" id="aksrt-doc-search">
<i class="fas fa-search aksrt-doc-nav__search-icon"></i>
</div>
<div class="aksrt-doc-search__results" data-aksrt-doc-search-results hidden></div>
<?php if (!empty($pages)) : ?>
<!-- Toolbar: category chips -->
<div class="aksrt-doc-toolbar">
<div class="aksrt-doc-toolbar__chips">
<button type="button" class="aksrt-doc-toolbar__chip is-active" data-cat-id="0"><?php esc_html_e('全部', 'aksrt'); ?></button>
<?php foreach ($pages as $p) : ?>
<button type="button" class="aksrt-doc-toolbar__chip" data-cat-id="<?php echo (int) $p->ID; ?>"><?php echo esc_html($p->post_title); ?></button>
<?php endforeach; ?>
</div>
<span class="aksrt-doc-toolbar__meta"><?php printf(esc_html__('%d 篇文档', 'aksrt'), count($pages)); ?></span>
</div>
<?php endif; ?>
<div class="aksrt-doc-nav__layout">
<!-- Document index cards -->
<div class="aksrt-doc-nav__main">
<?php if (!empty($pages)) : ?>
<div class="aksrt-doc-nav__grid">
<?php foreach ($pages as $p) :
$children = $presenter
? $presenter->get_flat_tree($p->ID, 1)
: get_pages([
'child_of' => $p->ID,
'sort_column' => 'menu_order',
'sort_order' => 'ASC',
'parent' => $p->ID,
'post_status' => 'publish',
]);
$child_count = count($children);
$thumb = get_the_post_thumbnail_url($p->ID, 'medium');
$excerpt = wp_trim_words($p->post_excerpt, 30, '...');
?>
<a href="<?php echo esc_url(get_permalink($p->ID)); ?>" class="aksrt-doc-index-card" data-cat-id="<?php echo (int) $p->ID; ?>">
<?php if ($thumb) : ?>
<div class="aksrt-doc-index-card__thumb">
<img src="<?php echo esc_url($thumb); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
</div>
<?php else : ?>
<div class="aksrt-doc-index-card__icon">
<i class="fas fa-book-open"></i>
</div>
<?php endif; ?>
<div class="aksrt-doc-index-card__body">
<h3 class="aksrt-doc-index-card__title"><?php echo esc_html($p->post_title); ?></h3>
<?php if ($excerpt) : ?>
<p class="aksrt-doc-index-card__desc"><?php echo esc_html($excerpt); ?></p>
<?php endif; ?>
<div class="aksrt-doc-index-card__meta">
<?php if ($child_count > 0) : ?>
<span class="aksrt-doc-index-card__count">
<i class="fas fa-file-alt"></i>
<?php printf(esc_html__('%d 篇文章', 'aksrt'), $child_count); ?>
</span>
<?php endif; ?>
<span class="aksrt-doc-index-card__date">
<i class="fas fa-clock"></i>
<?php echo esc_html(get_the_date('', $p->ID)); ?>
</span>
</div>
</div>
<i class="fas fa-chevron-right aksrt-doc-index-card__arrow"></i>
</a>
<?php endforeach; ?>
</div>
<?php else : ?>
<div class="aksrt-doc-nav__empty">
<i class="fas fa-book-open"></i>
<p><?php esc_html_e('暂无文档页面。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
</div>
<!-- Sidebar: Recent updates -->
<?php if ($show_sidebar && !empty($recent_pages)) : ?>
<aside class="aksrt-doc-nav__sidebar sidebar">
<div class="aksrt-doc-nav__recent">
<h3 class="aksrt-doc-nav__recent-title">
<i class="fas fa-clock"></i>
<?php esc_html_e('最近更新', 'aksrt'); ?>
</h3>
<ul class="aksrt-doc-nav__recent-list">
<?php foreach ($recent_pages as $rp) : ?>
<li class="aksrt-doc-nav__recent-item">
<a href="<?php echo esc_url(get_permalink($rp->ID)); ?>">
<span class="aksrt-doc-nav__recent-name"><?php echo esc_html($rp->post_title); ?></span>
<time class="aksrt-doc-nav__recent-date"><?php echo esc_html(get_the_date('', $rp->ID)); ?></time>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
</aside>
<?php endif; ?>
</div>
</div>
</div>
<?php
if (comments_open() || get_comments_number()) {
comments_template();
}
?>
</div>
</div>
<?php get_sidebar(); ?>
</main>
<?php
get_footer();