前言
因为自己喜欢倒腾,所以从Corenext换成了子比,但不代表Corenext不好,Corenext主题绝对是做博客的首选。
我换成子比是为了倒腾一些小玩意,今天就给大家带来自己弄的一个美化版的文章归档页面
展示
![图片[1]-子比主题文章归档页面美化版-新锐博客](https://www.xrbk.cn/wp-content/uploads/95c736762fcf8fd3e49521ef0bd5f3e2.webp)
![图片[2]-子比主题文章归档页面美化版-新锐博客](https://www.xrbk.cn/wp-content/uploads/cfffce8de30292a39d035bd6c7dd7061.webp)
教程
在子比主题的pages目录下创建一个新的php,名字随便命名,然后将如下代码放入进去
<?php
/**
* Template name: 新锐-文章归档
* Description: 文章归档页面,包含统计数据和文章列表
*/
// 获取分类统计信息并缓存
function get_category_statistics() {
return get_cached_data('category_stats', function() {
$categories = get_categories(['hide_empty' => false]);
$data = [];
foreach ($categories as $category) {
$data[] = ['value' => $category->count, 'name' => $category->name];
}
return json_encode($data);
});
}
// 获取最近一年每月的文章数量并缓存
function get_monthly_post_data() {
return get_cached_data('monthly_post_data', function() {
global $wpdb;
$query = "
SELECT DATE_FORMAT(post_date, '%Y-%m') AS month, COUNT(*) AS count
FROM {$wpdb->posts}
WHERE post_type = 'post' AND post_status = 'publish'
AND post_date >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR)
GROUP BY month
ORDER BY month ASC
";
$results = $wpdb->get_results($query, ARRAY_A);
$monthly_data = [];
foreach ($results as $result) {
$monthly_data[] = [
'month' => $result['month'],
'count' => $result['count']
];
}
return json_encode($monthly_data);
});
}
// 缓存处理函数
function get_cached_data($transient_key, $callback) {
if (false === ($data = get_transient($transient_key))) {
$data = call_user_func($callback);
set_transient($transient_key, $data, 12 * HOUR_IN_SECONDS);
}
return $data;
}
// 统计小工具
function render_archives_widgets($type = 'day') {
$icons = [
'day' => ['icon' => 'fa fa-calendar', 'color' => 'c-blue', 'title' => '运营时间'],
'post' => ['icon' => 'fa fa-file-text', 'color' => 'c-green', 'title' => '文章总数'],
'comment' => ['icon' => 'fa fa-comments', 'color' => 'c-purple', 'title' => '评论总数'],
'user' => ['icon' => 'fa fa-users', 'color' => 'c-orange', 'title' => '注册用户']
];
switch ($type) {
case 'day':
$first_post = get_posts(['numberposts' => 1, 'order' => 'ASC']);
$start_time = !empty($first_post) ? strtotime($first_post[0]->post_date) : time();
$statistic = round((time() - $start_time) / DAY_IN_SECONDS) . ' 天';
break;
case 'post':
$statistic = wp_count_posts()->publish;
break;
case 'comment':
$statistic = get_comment_count()['total_comments'];
break;
case 'user':
$statistic = count_users()['total_users'];
break;
default: return;
}
echo '<div class="stats-widget">';
echo '<div class="stats-header">'.$icons[$type]['title'].'</div>';
echo '<div class="stats-content">';
echo '<div class="stats-icon"><i class="'.$icons[$type]['icon'].' '.$icons[$type]['color'].'"></i></div>';
echo '<div class="stats-value">'.$statistic.'</div>';
echo '</div></div>';
}
// 注册脚本
function grace_archives_scripts() {
wp_enqueue_script('echarts', 'https://cdn.jsdmirror.com/npm/echarts@5.4.0/dist/echarts.min.js', [], null, true);
wp_enqueue_script('archives-script', get_template_directory_uri().'/js/archives.js', ['echarts', 'jquery'], null, true);
// 将数据传递给 JavaScript
wp_localize_script('archives-script', 'graceData', [
'postData' => json_decode(get_category_statistics()),
'monthlyPostData' => json_decode(get_monthly_post_data()),
'ajaxUrl' => admin_url('admin-ajax.php')
]);
}
add_action('wp_enqueue_scripts', 'grace_archives_scripts');
// AJAX 处理翻页请求
function load_more_posts() {
$paged = isset($_POST['page']) ? intval($_POST['page']) : 1;
$posts_per_page = 20;
$query = new WP_Query([
'posts_per_page' => $posts_per_page,
'paged' => $paged,
'orderby' => 'post_date',
'order' => 'DESC',
'post_status' => 'publish'
]);
if ($query->have_posts()) :
$organized = [];
while ($query->have_posts()) : $query->the_post();
$year = get_the_time('Y');
$month = get_the_time('m');
$organized[$year][$month][] = $post;
endwhile;
ob_start();
foreach ($organized as $year => $months) : ?>
<div class="archive-year">
<h2 class="year-title"><?php echo $year; ?></h2>
<?php foreach ($months as $month => $posts) : ?>
<div class="archive-month">
<h3 class="month-title"><?php echo date('n月', mktime(0, 0, 0, $month, 1)); ?></h3>
<ul class="post-list">
<?php foreach ($posts as $post) : setup_postdata($post); ?>
<li>
<time><?php the_time('m-d'); ?></time>
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
<?php the_title(); ?>
<?php if (get_comments_number()) : ?>
<span class="comment-count">(<?php echo get_comments_number(); ?>)</span>
<?php endif; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endforeach; ?>
</div>
<?php endforeach;
// 生成新的分页链接
$pagination = paginate_links([
'total' => $query->max_num_pages,
'current' => $paged,
'prev_next' => true,
'prev_text' => __('« 上一页'),
'next_text' => __('下一页 »'),
'echo' => false
]);
$output = ob_get_clean();
wp_send_json_success([
'data' => $output,
'pagination' => $pagination
]);
else :
wp_send_json_error('No more posts');
endif;
wp_reset_postdata();
wp_die();
}
add_action('wp_ajax_load_more_posts', 'load_more_posts');
add_action('wp_ajax_nopriv_load_more_posts', 'load_more_posts');
get_header();
?>
<main class="grace-archives">
<div class="archive-container">
<div class="archive-main">
<article class="archive-article">
<header class="archive-header">
<h1><?php the_title(); ?></h1>
<!-- 统计小工具 -->
<div class="stats-grid">
<?php
render_archives_widgets('day');
render_archives_widgets('post');
render_archives_widgets('comment');
render_archives_widgets('user');
?>
</div>
</header>
<!-- 图表区域 -->
<div class="charts-container">
<div class="chart-box" id="postChart"></div>
<div class="chart-box" id="monthlyPostChart"></div>
</div>
<!-- 文章列表 -->
<div class="archives-list">
<?php
// 获取当前页码
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$posts_per_page = 20;
$query = new WP_Query([
'posts_per_page' => $posts_per_page,
'paged' => $paged,
'orderby' => 'post_date',
'order' => 'DESC',
'post_status' => 'publish'
]);
if ($query->have_posts()) :
$organized = [];
while ($query->have_posts()) : $query->the_post();
$year = get_the_time('Y');
$month = get_the_time('m');
$organized[$year][$month][] = $post;
endwhile;
foreach ($organized as $year => $months) : ?>
<div class="archive-year">
<h2 class="year-title"><?php echo $year; ?></h2>
<?php foreach ($months as $month => $posts) : ?>
<div class="archive-month">
<h3 class="month-title"><?php echo date('n月', mktime(0, 0, 0, $month, 1)); ?></h3>
<ul class="post-list">
<?php foreach ($posts as $post) : setup_postdata($post); ?>
<li>
<time><?php the_time('m-d'); ?></time>
<a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
<?php the_title(); ?>
<?php if (get_comments_number()) : ?>
<span class="comment-count">(<?php echo get_comments_number(); ?>)</span>
<?php endif; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endforeach; ?>
</div>
<?php endforeach;
else :
echo '<p>暂无文章</p>';
endif;
wp_reset_postdata();
?>
</div>
<!-- 传统分页 -->
<div class="archive-pagination">
<?php
echo paginate_links([
'total' => $query->max_num_pages,
'current' => $paged,
'prev_next' => true,
'prev_text' => __('« 上一页'),
'next_text' => __('下一页 »'),
'type' => 'plain', // 修改这里
'mid_size' => 2 // 控制显示页码数量
]);
?>
</div>
</article>
</div>
</div>
</main>
<script>
// 仅保留图表初始化代码
jQuery(document).ready(function($) {
// 初始化 ECharts 图表
const postChart = echarts.init(document.getElementById('postChart'));
const monthlyPostChart = echarts.init(document.getElementById('monthlyPostChart'));
postChart.setOption({
title: { text: '文章分类分布' },
tooltip: { trigger: 'item' },
series: [{
type: 'pie',
data: graceData.postData
}]
});
monthlyPostChart.setOption({
title: { text: '每月发文数量' },
tooltip: { trigger: 'axis' },
xAxis: {
type: 'category',
data: graceData.monthlyPostData.map(item => item.month)
},
yAxis: { type: 'value' },
series: [{
type: 'line',
data: graceData.monthlyPostData.map(item => item.count)
}]
});
});
</script>
<style>
.grace-archives {
padding: 2rem 20px;
background: #f8f9fa;
min-height: 100vh;
}
/* 分页容器 */
.archive-pagination {
margin-top: 3rem;
text-align: center;
}
/* 分页链接基础样式 */
.archive-pagination a,
.archive-pagination span {
display: inline-block;
padding: 8px 16px;
margin: 0 4px;
border: 1px solid #e0e0e0;
border-radius: 4px;
color: #3498db;
text-decoration: none;
transition: all 0.3s;
}
/* 当前页样式 */
.archive-pagination span.current {
background: #3498db;
color: white;
border-color: #3498db;
}
/* 悬停效果 */
.archive-pagination a:hover {
background: #f8f9fa;
border-color: #3498db;
}
/* 移动端适配 */
@media (max-width: 480px) {
.archive-pagination a,
.archive-pagination span {
padding: 6px 12px;
margin: 2px;
font-size: 14px;
}
}
.archive-container {
max-width: 1400px;
margin: 0 auto;
}
.archive-main {
background: #fff;
border-radius: 12px;
padding: 2rem;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.archive-header {
margin-bottom: 2rem;
border-bottom: 2px solid #f0f0f0;
padding-bottom: 1.5rem;
}
.archive-header h1 {
font-size: 2.2rem;
color: #2c3e50;
margin: 0 0 1.5rem;
}
/* 统计小工具 */
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.5rem;
margin: 2rem 0;
}
.stats-widget {
background: #ffffff;
border: 1px solid #eaeaea;
padding: 1.5rem;
border-radius: 10px;
transition: transform 0.3s ease;
}
.stats-widget:hover {
transform: translateY(-3px);
box-shadow: 0 6px 16px rgba(0,0,0,0.1);
}
.stats-header {
color: #7f8c8d;
font-size: 0.95rem;
margin-bottom: 0.8rem;
font-weight: 500;
}
.stats-content {
display: flex;
align-items: center;
gap: 1.2rem;
}
.stats-icon i {
font-size: 2rem;
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
}
.stats-value {
font-size: 1.8rem;
font-weight: 600;
color: #2c3e50;
}
/* 颜色定义 */
.c-blue { background: #e3f2fd; color: #2196f3; }
.c-green { background: #e8f5e9; color: #4caf50; }
.c-purple { background: #f3e5f5; color: #9c27b0; }
.c-orange { background: #fff3e0; color: #ff9800; }
/* 图表容器 */
.charts-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1.5rem;
margin: 3rem 0;
}
.chart-box {
height: 400px;
background: #fff;
border: 1px solid #eee;
border-radius: 10px;
padding: 1rem;
}
/* 文章列表 */
.archives-list {
margin-top: 2rem;
}
.archive-year {
margin-bottom: 3rem;
background: #fafafa;
border-radius: 8px;
padding: 1.5rem;
}
.year-title {
font-size: 1.8rem;
color: #2c3e50;
margin: 0 0 1.5rem;
padding-bottom: 0.8rem;
border-bottom: 2px solid #eee;
}
.archive-month {
margin-bottom: 2rem;
background: #fff;
border-radius: 6px;
padding: 1rem;
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
}
.month-title {
font-size: 1.4rem;
color: #34495e;
margin: 0 0 1rem;
padding-left: 0.5rem;
}
.post-list {
list-style: none;
padding: 0;
margin: 0;
}
.post-list li {
padding: 1rem 1.2rem;
border-bottom: 1px solid #f5f5f5;
display: flex;
align-items: center;
gap: 1.5rem;
transition: background 0.3s;
}
.post-list li:hover {
background: #f8f9fa;
}
.post-list time {
color: #7f8c8d;
min-width: 70px;
font-family: monospace;
font-size: 0.95rem;
}
.post-list a {
color: #2c3e50;
transition: color 0.3s;
flex-grow: 1;
text-decoration: none;
font-weight: 500;
}
.post-list a:hover {
color: #3498db;
}
.comment-count {
color: #95a5a6;
font-size: 0.85em;
margin-left: 0.8rem;
font-weight: normal;
}
/* 分页样式 */
.archive-pagination {
margin-top: 3rem;
text-align: center;
padding: 1.5rem 0;
}
.archive-pagination .page-numbers {
display: inline-block;
padding: 8px 16px;
margin: 0 5px;
border: 1px solid #e0e0e0;
border-radius: 6px;
color: #3498db;
text-decoration: none;
transition: all 0.3s;
}
.archive-pagination .page-numbers.current {
background: #3498db;
color: #fff;
border-color: #3498db;
}
.archive-pagination .page-numbers:hover:not(.current) {
background: #f8f9fa;
border-color: #3498db;
}
/* 加载提示 */
.loading {
text-align: center;
padding: 1.5rem;
color: #7f8c8d;
font-size: 0.95rem;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.charts-container {
grid-template-columns: 1fr;
}
.chart-box {
height: 350px;
}
}
@media (max-width: 768px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.stats-value {
font-size: 1.6rem;
}
.archive-main {
padding: 1.5rem;
}
.year-title {
font-size: 1.6rem;
}
}
@media (max-width: 480px) {
.stats-grid {
grid-template-columns: 1fr;
}
.stats-content {
gap: 1rem;
}
.archive-pagination .page-numbers {
padding: 6px 12px;
margin: 3px;
}
.post-list li {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
padding: 1rem;
}
}
</style>
<?php get_footer(); ?>
再到子比主题根目录里的JS文件夹里创建一个archives.js的文件,然后将如下代码放进去
// archives.js 完整代码
document.addEventListener('DOMContentLoaded', function() {
const chartContainers = [
'postChart',
'monthlyPostChart'
];
chartContainers.forEach(id => {
const el = document.getElementById(id);
if (!el) {
console.warn(`图表容器 #${id} 未找到`);
return;
}
try {
// 初始化图表代码...
} catch (error) {
console.error(`初始化图表 ${id} 失败:`, error);
}
});
// 获取图表容器
const postChartEl = document.getElementById('postChart');
const monthlyChartEl = document.getElementById('monthlyPostChart');
// 检查元素是否存在
if (!postChartEl || !monthlyChartEl) {
console.warn('图表容器未找到,请检查元素ID是否正确');
return;
}
// 初始化图表实例
const postChart = echarts.init(postChartEl);
const monthlyPostChart = echarts.init(monthlyChartEl);
// 配置分类分布饼图
postChart.setOption({
title: { text: '文章分类分布', left: 'center' },
tooltip: { trigger: 'item' },
series: [{
type: 'pie',
radius: '55%',
data: graceData.postData,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
});
// 配置月度趋势折线图
monthlyPostChart.setOption({
title: { text: '月度发文趋势', left: 'center' },
tooltip: { trigger: 'axis' },
xAxis: {
type: 'category',
data: graceData.monthlyPostData.map(item => item.month),
axisLabel: { rotate: 45 }
},
yAxis: { type: 'value' },
series: [{
type: 'line',
smooth: true,
data: graceData.monthlyPostData.map(item => item.count),
areaStyle: { color: 'rgba(52, 152, 219, 0.2)' }
}],
grid: { containLabel: true }
});
// 窗口大小变化时自适应
window.addEventListener('resize', function() {
postChart.resize();
monthlyPostChart.resize();
});
});
最后再到页面中选择新锐-文章归档模版即可
© 版权声明
THE END
暂无评论内容