子比文章归档页面模板 | 代码公开 & 结合AI开发-zibll美化交流分享社区-zibll子比主题-WordPress主题模板-zibll子比主题

子比文章归档页面模板 | 代码公开 & 结合AI开发

本模板是在子比文章归档页面模板【二次开发版】的基础上利用AI进行开发,代码有点臃肿,请见谅!

搭建步骤可以参考上面的文章,模板步骤的话,等我有空了补上。

感谢初一提供的思路,其实做了很久了,没空发,后续还要再优化代码和界面!!!

示例网址:文章归档-聪明才智亦如你

参考页面图:

20250416231353624-image-20

20250416231413368-image-21

20250416231437910-image-22

20250416231502715-image-23

我使用的完整代码(后续还会再次优化),结合AI写的代码,有点臃肿,请见谅:

<?php
/**
 * Template name: Grace-文章归档新版
 * Description: A modern archives page with article statistics and visualizations
 *
 * 设计理念:数据接口使用缓存,前端图表使用 Chart.js,整体视觉采用白色/浅灰背景搭配柔和蓝绿主色调,
 * 突出高级感与艺术气息,适合长期运营、海量文章的网站。
 */

/* ============================= 数据统计及缓存函数 ============================= */

// 获取分类统计信息并缓存,只显示文章数量前26的分类
function get_category_statistics() {
    return get_cached_data('category_stats_top26', function() {
        $categories = get_categories([
            'hide_empty' => false,
            'orderby'    => 'count',
            'order'      => 'DESC',
            'number'     => 26
        ]);
        $data = [];
        foreach ($categories as $category) {
            $data[] = ['value' => $category->count, 'name' => $category->name];
        }
        return json_encode($data);
    });
}

// 获取文章热力图数据(按天统计)
function get_heatmap_data() {
    return get_cached_data('heatmap_data', function() {
        global $wpdb;
        $query = "
            SELECT DATE(post_date) AS date, COUNT(*) AS count
            FROM {$wpdb->posts}
            WHERE post_type = 'post' AND post_status = 'publish'
            GROUP BY DATE(post_date)
            ORDER BY date ASC
        ";
        $results = $wpdb->get_results($query, ARRAY_A);
        if (!empty($results)) {
            $start_date = $results[0]['date'];
            $end_date   = end($results)['date'];
            $current_date = strtotime($start_date);
            $heatmap_data = [];
            while (date('Y-m-d', $current_date) <= $end_date) {
                $formatted_date = date('Y-m-d', $current_date);
                $count = 0;
                foreach ($results as $result) {
                    if ($result['date'] === $formatted_date) {
                        $count = $result['count'];
                        break;
                    }
                }
                $heatmap_data[] = [$formatted_date, $count];
                $current_date = strtotime('+1 day', $current_date);
            }
            return json_encode($heatmap_data);
        } else {
            return json_encode([]);
        }
    });
}

// 获取月度文章发布统计数据
function get_monthly_post_data() {
    return get_cached_data('monthly_posts', 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'
            GROUP BY DATE_FORMAT(post_date, '%Y-%m')
            ORDER BY month ASC
        ";
        $results = $wpdb->get_results($query, ARRAY_A);
        $data = [];
        if (!empty($results)) {
            $months = [];
            $counts = [];
            foreach ($results as $result) {
                $months[] = $result['month'];
                $counts[] = (int)$result['count'];
            }
            $data = ['months' => $months, 'counts' => $counts];
        }
        return json_encode($data);
    });
}

// 获取用户VIP统计数据
function get_user_vip_statistics() {
    return get_cached_data('user_vip_stats', function() {
        $users = get_users(['fields' => ['ID']]);
        $user_counts = [
            'normal' => 0,
            'vip_1'  => 0,
            'vip_2'  => 0
        ];
        foreach ($users as $user) {
            $vip_level = zib_get_user_vip_level($user->ID);
            switch ($vip_level) {
                case 1:
                    $user_counts['vip_1']++;
                    break;
                case 2:
                    $user_counts['vip_2']++;
                    break;
                default:
                    $user_counts['normal']++;
                    break;
            }
        }
        $chart_data = [
            ['value' => $user_counts['normal'], 'name' => '普通用户'],
            ['value' => $user_counts['vip_1'], 'name' => _pz('pay_user_vip_1_name')],
            ['value' => $user_counts['vip_2'], 'name' => _pz('pay_user_vip_2_name')]

        ];
        return json_encode($chart_data);
    });
}

// 缓存数据函数(使用 WordPress 瞬态 API)
function get_cached_data($transient_key, $fetch_callback) {
    if (false === ($data = get_transient($transient_key))) {
        $data = call_user_func($fetch_callback);
        set_transient($transient_key, $data, DAY_IN_SECONDS);
    }
    return $data;
}

// 访问统计:总访问量
function get_total_visit_count() {
    global $wpdb;
    $count = 0;
    $views = $wpdb->get_results("SELECT meta_value FROM $wpdb->postmeta WHERE meta_key='views'");
    if (!empty($views)) {
        foreach ($views as $view) {
            if (trim($view->meta_value) !== '') {
                $count += (int)$view->meta_value;
            }
        }
    }
    return $count;
}

// 今日统计数据
function get_today_new_users() {
    global $wpdb;
    $today = current_time('Y-m-d');
    $count = $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->users} WHERE DATE(user_registered) = '$today'");
    return $count ? intval($count) : 0;
}
function get_today_new_posts() {
    global $wpdb;
    $today = current_time('Y-m-d');
    $count = $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_type='post' AND post_status='publish' AND DATE(post_date) = '$today'");
    return $count ? intval($count) : 0;
}
function get_today_new_comments() {
    global $wpdb;
    $today = current_time('Y-m-d');
    $count = $wpdb->get_var("SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE DATE(comment_date) = '$today' AND comment_approved = '1'");
    return $count ? intval($count) : 0;
}

// 获取按年份分组的文章列表
function get_posts_by_year() {
    global $wpdb;
    $years_query = $wpdb->get_results(
        "SELECT YEAR(post_date) as year
         FROM $wpdb->posts
         WHERE post_type = 'post' AND post_status = 'publish'
         GROUP BY YEAR(post_date)
         ORDER BY year DESC"
    );
    $years = [];
    foreach ($years_query as $year_item) {
        $year = $year_item->year;
        $posts_in_year = get_posts([
            'numberposts' => -1,
            'post_type'    => 'post',
            'post_status'  => 'publish',
            'date_query'   => [['year' => $year]],
            'orderby'      => 'date',
            'order'        => 'DESC'
        ]);
        $posts_by_month = [];
        foreach ($posts_in_year as $post) {
            $month = mysql2date('m', $post->post_date);
            $month_name = mysql2date('F', $post->post_date);
            if (!isset($posts_by_month[$month])) {
                $posts_by_month[$month] = [
                    'name'  => $month_name,
                    'posts' => []
                ];
            }
            $posts_by_month[$month]['posts'][] = [
                'id'        => $post->ID,
                'title'     => $post->post_title,
                'date'      => get_the_date('Y-m-d', $post),
                'permalink' => get_permalink($post)
            ];
        }
        ksort($posts_by_month);
        $years[$year] = [
            'months' => $posts_by_month,
            'count'  => count($posts_in_year)
        ];
    }
    return $years;
}

/* ============================= 脚本加载与数据传递 ============================= */
function grace_archives_new_scripts() {
    wp_enqueue_script('chart-js', 'https://cdn.jsdelivr.net/npm/chart.js', [], null, true);
    wp_enqueue_script('charts-utils', 'https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns', ['chart-js'], null, true);
    // 将数据传递给 JS
    wp_enqueue_script('archives-modern-js', get_theme_file_uri('/assets/js/archives-modern.js'), ['chart-js', 'jquery'], null, true);
    $data_to_js = [
        'categoryData' => json_decode(get_category_statistics(), true),
        'heatmapData'  => json_decode(get_heatmap_data(), true),
        'monthlyData'  => json_decode(get_monthly_post_data(), true),
        'userVipData'  => json_decode(get_user_vip_statistics(), true)
    ];
    wp_localize_script('archives-modern-js', 'archivesData', $data_to_js);
}
add_action('wp_enqueue_scripts', 'grace_archives_new_scripts');

get_header();
$post_id        = get_queried_object_id();
$header_style   = zib_get_page_header_style($post_id);
$post_count     = wp_count_posts()->publish;
$comment_data   = get_comment_count();
$total_comments = $comment_data['approved'] + $comment_data['moderated'] + $comment_data['spam'] + $comment_data['trash'];
$user_count     = count_users()['total_users'];
$posts_by_year  = get_posts_by_year();
?>

<!-- 内嵌样式:高级感、炫酷且富有艺术气息 -->
<style>
:root {
    --card-bg: #ffffff;
    --text-main: #333333;
    --text-secondary: #777777;
    --border-color: rgba(0,0,0,0.1);
    --hover-bg: rgba(0,0,0,0.03);
    --accent-color: #3498db;
    --accent-soft: rgba(52,152,219,0.1);
    --chart-grid: rgba(0,0,0,0.05);
    --shadow-soft: 0 2px 8px rgba(0,0,0,0.05);
    --shadow-medium: 0 4px 12px rgba(0,0,0,0.1);
    --rounded-sm: 4px;
    --rounded-md: 8px;
    --rounded-lg: 12px;
    --anim-standard: all 0.3s ease;
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    background: #f7f7f7;
    color: var(--text-main);
    line-height: 1.6;
}
body.dark {
    /* 高级暗色风:淡灰蓝背景 */
    --card-bg: #f1f3f5;
    --text-main: #2c3e50;
    --text-secondary: #6c757d;
    --border-color: rgba(0,0,0,0.1);
    --hover-bg: rgba(0,0,0,0.03);
    --chart-grid: rgba(0,0,0,0.05);
    --shadow-soft: 0 2px 8px rgba(0,0,0,0.05);
    --shadow-medium: 0 4px 12px rgba(0,0,0,0.1);
}
.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}
.stats-overview,
.dashboard-grid,
.archive-section {
    margin-bottom: 32px;
}
/* Stat Cards */
.stat-card {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: var(--rounded-md);
    padding: 20px;
    box-shadow: var(--shadow-soft);
    transition: var(--anim-standard);
    display: flex;
    align-items: center;
    position: relative;
}
.stat-card:hover {
    box-shadow: var(--shadow-medium);
    transform: translateY(-2px);
}
.stat-icon {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 16px;
    flex-shrink: 0;
}
.stat-content { flex-grow: 1; }
.stat-title { color: var(--text-secondary); font-size: 14px; margin-bottom: 6px; }
.stat-value { color: var(--text-main); font-size: 22px; font-weight: 600; }
.stat-note { color: var(--text-secondary); font-size: 12px; }
/* Chart Cards */
.chart-card {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: var(--rounded-md);
    padding: 20px;
    box-shadow: var(--shadow-soft);
    margin-bottom: 24px;
    position: relative;
}
.chart-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
}
.chart-title { color: var(--text-main); font-size: 20px; font-weight: bold; }
.chart-container { position: relative; height: 300px; width: 100%; }
/* Archive Section */
.archive-section {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: var(--rounded-md);
    padding: 24px;
    box-shadow: var(--shadow-soft);
    margin-bottom: 24px;
}
.archive-title {
    color: var(--text-main);
    font-size: 22px;
    font-weight: bold;
    margin-bottom: 20px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 12px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.archive-year { margin-bottom: 24px; }
.year-header, .month-header {
    background: var(--accent-soft);
    color: var(--accent-color);
    padding: 10px 16px;
    border-radius: var(--rounded-sm);
    cursor: pointer;
    margin-bottom: 12px;
    transition: var(--anim-standard);
}
.year-header:hover, .month-header:hover { background: var(--hover-bg); }
.year-title, .month-header { font-size: 18px; }
.year-count {
    font-size: 14px;
    background: var(--accent-color);
    color: #fff;
    border-radius: 20px;
    padding: 2px 10px;
}
.month-section { margin-left: 12px; position: relative; }
.post-list { margin-left: 20px; display: none; }
.post-item {
    display: flex;
    align-items: center;
    padding: 8px 10px;
    border-bottom: 1px dashed var(--border-color);
    transition: var(--anim-standard);
}
.post-item:last-child { border-bottom: none; }
.post-date { color: var(--text-secondary); font-size: 13px; width: 95px; margin-right: 12px; }
.post-title a {
    color: var(--text-main);
    text-decoration: none;
    transition: var(--anim-standard);
}
.post-title a:hover { color: var(--accent-color); }
/* Utility classes */
.mb-lg { margin-bottom: 32px; }
.expand-all-button {
    background: var(--accent-color);
    color: #fff;
    border: none;
    border-radius: var(--rounded-sm);
    padding: 6px 12px;
    font-size: 14px;
    cursor: pointer;
    transition: var(--anim-standard);
}
.expand-all-button:hover { opacity: 0.9; }
.toggle-icon { transition: transform 0.3s ease; }
.toggle-icon.open { transform: rotate(180deg); }
.dashboard-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    margin-bottom: 32px;
}
@media (max-width: 900px) {
    .dashboard-grid { grid-template-columns: 1fr; }
    .chart-container { height: 250px; }
}
@media (max-width: 480px) {
    .post-date { width: 85px; }
}

/* ========== 3D动画效果样式 ========== */
.archives-3d-header {
    position: relative;
    width: 100%;
    height: 60vh;
    min-height: 400px;
    max-height: 800px;
    overflow: hidden;
    margin-bottom: 40px;
    background-color: #000;
    color: #fff;
}

.archives-3d-header * {
    box-sizing: border-box;
}

/* square 仅用于鼠标跟踪效果 */
#square {
    position: fixed;
    left: 50vw;
    top: -100px;
    background-color: #fff;
    width: 100px;
    height: 100px;
    transform: translate(-50%, -50%);
    pointer-events: none;
    mix-blend-mode: difference;
    z-index: 10;
}

/* 修改 .boxes 容器:占满父容器并使用 flex 居中 */
.boxes {
    --boxWidth: 300px;
    --boxTranslate: calc(var(--boxWidth) / 2 + 2px);
    --pers: calc(var(--boxWidth) * 3);
    position: absolute;
    z-index: 1;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 !important;
}

.boxes a {
    text-decoration: unset;
    color: #fff;
}

/* 取消鼠标悬停时 outline 效果 */
.boxes a.target .boxes__box__face:not(.boxes__box__face--inside),
.boxes a:hover .boxes__box__face:not(.boxes__box__face--inside) {
    /* outline: #fff solid 5px; */
}

.boxes p {
    color: #000;
    -webkit-text-stroke-width: 2px;
    -webkit-text-stroke-color: #fff;
    font-size: 4rem;
    line-height: 1.15;
    width: min-content;
    text-transform: uppercase;
}

/* 调整子盒子定位:使用百分比单位 */
.boxes__back,
.boxes__scene {
    position: absolute;
    transform: translate(-50%, -50%);
    width: var(--boxWidth);
    height: var(--boxWidth);
    perspective: var(--pers);
}

.boxes__back--1,
.boxes__scene--1 {
    left: 30%;
    top: 40%;
    animation: move-1 18s infinite ease-in-out;
}

.boxes__back--1 .boxes__box,
.boxes__scene--1 .boxes__box {
    animation: float-1 20s infinite ease-in-out;
}

.boxes__back--2,
.boxes__scene--2 {
    left: 45%;
    top: 70%;
    animation: move-2 18s infinite ease-in-out;
}

.boxes__back--2 .boxes__box,
.boxes__scene--2 .boxes__box {
    animation: float-2 20s infinite ease-in-out;
}

.boxes__back--3,
.boxes__scene--3 {
    left: 50%;
    top: 30%;
    animation: move-3 18s infinite ease-in-out;
}

.boxes__back--3 .boxes__box,
.boxes__scene--3 .boxes__box {
    animation: float-3 20s infinite ease-in-out;
}

/* 盒子各面 */
.boxes__box {
    width: 100%;
    height: 100%;
    position: relative;
    transform: translateZ(-100px);
    transform-style: preserve-3d;
}

.boxes__box__face {
    position: absolute;
    width: var(--boxWidth);
    height: var(--boxWidth);
    display: flex;
    justify-content: center;
    align-items: center;
    backface-visibility: visible;
    border-radius: 0.5px;
    border: 1px solid #fff;
}

/* 内部面取消边框 */
.boxes__box__face--inside {
    border: none;
    transform: rotateY(0) translateZ(0);
}

.boxes__box__face--front {
    transform: rotateY(0) translateZ(var(--boxTranslate));
}

.boxes__box__face--right {
    transform: rotateY(90deg) translateZ(var(--boxTranslate));
}

.boxes__box__face--back {
    transform: rotateY(180deg) translateZ(var(--boxTranslate));
}

.boxes__box__face--left {
    transform: rotateY(-90deg) translateZ(var(--boxTranslate));
}

.boxes__box__face--top {
    transform: rotateX(90deg) translateZ(var(--boxTranslate));
}

.boxes__box__face--bottom {
    transform: rotateX(-90deg) translateZ(var(--boxTranslate));
}

@keyframes float-1 {
    0%, 100% {
        transform: translateZ(-100px) rotateY(-20deg) rotateX(-15deg) rotateZ(10deg);
    }
    30% {
        transform: translateZ(-100px) rotateY(-22deg) rotateX(-22deg) rotateZ(8deg);
    }
    50% {
        transform: translateZ(-100px) rotateY(-15deg) rotateX(-20deg) rotateZ(15deg);
    }
    66% {
        transform: translateZ(-100px) rotateY(-14deg) rotateX(-17deg) rotateZ(16deg);
    }
}

@keyframes float-2 {
    0%, 100% {
        transform: translateZ(-100px) rotateY(20deg) rotateX(-15deg) rotateZ(-10deg);
    }
    40% {
        transform: translateZ(-100px) rotateY(15deg) rotateX(-20deg) rotateZ(-15deg);
    }
    55% {
        transform: translateZ(-100px) rotateY(14deg) rotateX(-17deg) rotateZ(-16deg);
    }
    70% {
        transform: translateZ(-100px) rotateY(22deg) rotateX(-22deg) rotateZ(-8deg);
    }
}

@keyframes float-3 {
    0%, 100% {
        transform: translateZ(-100px) rotateY(-20deg) rotateX(-15deg) rotateZ(10deg);
    }
    40% {
        transform: translateZ(-100px) rotateY(-15deg) rotateX(-20deg) rotateZ(15deg);
    }
    55% {
        transform: translateZ(-100px) rotateY(-14deg) rotateX(-17deg) rotateZ(16deg);
    }
    70% {
        transform: translateZ(-100px) rotateY(-22deg) rotateX(-22deg) rotateZ(8deg);
    }
}

/* 调整 move-1 与 move-2 保持原效果 */
@keyframes move-1 {
    0%, 100% {
        transform: translate(-60%, -70%);
    }
    25% {
        transform: translate(-30%, -60%);
    }
    50% {
        transform: translate(-20%, -70%);
    }
    75% {
        transform: translate(-30%, -40%);
    }
}

@keyframes move-2 {
    0%, 100% {
        transform: translate(-50%, -50%);
    }
    25% {
        transform: translate(-40%, -50%);
    }
    50% {
        transform: translate(-50%, -60%);
    }
    75% {
        transform: translate(-50%, -40%);
    }
}

/* 修改 move-3,降低第三个盒子动画时的偏移,确保其始终在容器内可见 */
@keyframes move-3 {
    0%, 100% {
        transform: translate(-5%, -30%);
    }
    25% {
        transform: translate(0, -25%);
    }
    50% {
        transform: translate(5%, -30%);
    }
    75% {
        transform: translate(0, -35%);
    }
}

/* 响应式调整 */
@media screen and (max-width: 1024px) {
    .archives-3d-header {
        height: 50vh;
    }
    .boxes {
        --boxWidth: 250px;
    }
    .boxes p {
        font-size: 3rem;
    }
}

@media screen and (max-width: 768px) {
    .archives-3d-header {
        height: 40vh;
    }
    .boxes {
        --boxWidth: 200px;
    }
    .boxes p {
        font-size: 2.5rem;
        -webkit-text-stroke-width: 1.5px;
    }
}

@media screen and (max-width: 480px) {
    .archives-3d-header {
        height: 30vh;
        min-height: 300px;
    }
    .boxes {
        --boxWidth: 150px;
    }
    .boxes p {
        font-size: 2rem;
        -webkit-text-stroke-width: 1px;
    }
}
/* ========== 3D动画效果样式 结束 ========== */
</style>

<main class="container">
    <div class="content-wrap">
        <div class="content-layout">
            <?php if ($header_style != 1) { echo zib_get_page_header($post_id); } ?>
            <div class="theme-box">
                <?php if ($header_style == 1) { echo zib_get_page_header($post_id); } ?>
                
                <!-- 3D动画效果 - 开始 -->
                <div class="archives-3d-header">
                    <div class="archives-3d-container">
                        <div id="square"></div>
                        <div class="boxes">
                            <div class="boxes__back boxes__back--1">
                                <div class="boxes__box">
                                    <div class="boxes__box__face boxes__box__face--front"></div>
                                    <div class="boxes__box__face boxes__box__face--back"></div>
                                    <div class="boxes__box__face boxes__box__face--right"></div>
                                    <div class="boxes__box__face boxes__box__face--left"></div>
                                    <div class="boxes__box__face boxes__box__face--top"></div>
                                    <div class="boxes__box__face boxes__box__face--bottom"></div>
                                </div>
                            </div>

                            <div class="boxes__scene boxes__scene--1">
                                <div class="boxes__box">
                                    <div class="boxes__box__face boxes__box__face--inside">
                                        <p>文章归档</p>
                                    </div>
                                    <div class="boxes__box__face boxes__box__face--front"></div>
                                    <div class="boxes__box__face boxes__box__face--back"></div>
                                    <div class="boxes__box__face boxes__box__face--right"></div>
                                    <div class="boxes__box__face boxes__box__face--left"></div>
                                    <div class="boxes__box__face boxes__box__face--top"></div>
                                    <div class="boxes__box__face boxes__box__face--bottom"></div>
                                </div>
                            </div>

                            <div class="boxes__back boxes__back--2">
                                <div class="boxes__box">
                                    <div class="boxes__box__face boxes__box__face--front"></div>
                                    <div class="boxes__box__face boxes__box__face--back"></div>
                                    <div class="boxes__box__face boxes__box__face--right"></div>
                                    <div class="boxes__box__face boxes__box__face--left"></div>
                                    <div class="boxes__box__face boxes__box__face--top"></div>
                                    <div class="boxes__box__face boxes__box__face--bottom"></div>
                                </div>
                            </div>
                            <div class="boxes__scene boxes__scene--2">
                                <div class="boxes__box">
                                    <div class="boxes__box__face boxes__box__face--inside">
                                        <p>博客</p>
                                    </div>
                                    <div class="boxes__box__face boxes__box__face--front"></div>
                                    <div class="boxes__box__face boxes__box__face--back"></div>
                                    <div class="boxes__box__face boxes__box__face--right"></div>
                                    <div class="boxes__box__face boxes__box__face--left"></div>
                                    <div class="boxes__box__face boxes__box__face--top"></div>
                                    <div class="boxes__box__face boxes__box__face--bottom"></div>
                                </div>
                            </div>

                            <div class="boxes__back boxes__back--3">
                                <div class="boxes__box">
                                    <div class="boxes__box__face boxes__box__face--front"></div>
                                    <div class="boxes__box__face boxes__box__face--back"></div>
                                    <div class="boxes__box__face boxes__box__face--right"></div>
                                    <div class="boxes__box__face boxes__box__face--left"></div>
                                    <div class="boxes__box__face boxes__box__face--top"></div>
                                    <div class="boxes__box__face boxes__box__face--bottom"></div>
                                </div>
                            </div>
                            <div class="boxes__scene boxes__scene--3">
                                <div class="boxes__box">
                                    <div class="boxes__box__face boxes__box__face--inside">
                                        <p>时间轴</p>
                                    </div>
                                    <div class="boxes__box__face boxes__box__face--front"></div>
                                    <div class="boxes__box__face boxes__box__face--back"></div>
                                    <div class="boxes__box__face boxes__box__face--right"></div>
                                    <div class="boxes__box__face boxes__box__face--left"></div>
                                    <div class="boxes__box__face boxes__box__face--top"></div>
                                    <div class="boxes__box__face boxes__box__face--bottom"></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <!-- 3D动画效果 - 结束 -->
                
                <article>
                    <!-- 统计概览卡片 -->
                    <div class="stats-overview">
                        <div class="stat-card">
                            <div class="stat-icon" style="background-color: rgba(52,152,219,0.1);">
                                <i class="fa fa-file-text-o" style="color: #3498db; font-size: 22px;"></i>
                            </div>
                            <div class="stat-content">
                                <div class="stat-title">文章总数</div>
                                <div class="stat-value"><?php echo esc_html($post_count); ?></div>
                                <span class="stat-note">今日新增 <?php echo esc_html(get_today_new_posts()); ?></span>
                            </div>
                        </div>
                        <div class="stat-card">
                            <div class="stat-icon" style="background-color: rgba(46,204,113,0.1);">
                                <i class="fa fa-comments" style="color: #2ecc71; font-size: 22px;"></i>
                            </div>
                            <div class="stat-content">
                                <div class="stat-title">评论总数</div>
                                <div class="stat-value"><?php echo esc_html($total_comments); ?></div>
                                <span class="stat-note">今日新增 <?php echo esc_html(get_today_new_comments()); ?></span>
                            </div>
                        </div>
                        <div class="stat-card">
                            <div class="stat-icon" style="background-color: rgba(241,196,15,0.1);">
                                <i class="fa fa-users" style="color: #f1c40f; font-size: 22px;"></i>
                            </div>
                            <div class="stat-content">
                                <div class="stat-title">用户总数</div>
                                <div class="stat-value"><?php echo esc_html($user_count); ?></div>
                                <span class="stat-note">今日新增 <?php echo esc_html(get_today_new_users()); ?></span>
                            </div>
                        </div>
                        <div class="stat-card">
                            <div class="stat-icon" style="background-color: rgba(231,76,60,0.1);">
                                <i class="fa fa-eye" style="color: #e74c3c; font-size: 22px;"></i>
                            </div>
                            <div class="stat-content">
                                <div class="stat-title">访问总数</div>
                                <div class="stat-value"><?php echo esc_html(get_total_visit_count()); ?></div>
                            </div>
                        </div>
                    </div>
                    <!-- 图表仪表盘 -->
                    <div class="dashboard-grid">
                        <div class="chart-card">
                            <div class="chart-card-header">
                                <h3 class="chart-title">文章分类统计</h3>
                            </div>
                            <div class="chart-container">
                                <canvas id="category-chart"></canvas>
                            </div>
                        </div>
                        <div class="chart-card">
                            <div class="chart-card-header">
                                <h3 class="chart-title">用户类型分布</h3>
                            </div>
                            <div class="chart-container">
                                <canvas id="user-chart"></canvas>
                            </div>
                        </div>
                        <div class="chart-card">
                            <div class="chart-card-header">
                                <h3 class="chart-title">月度文章发布量</h3>
                            </div>
                            <div class="chart-container">
                                <canvas id="monthly-chart"></canvas>
                            </div>
                        </div>
                        <div class="chart-card">
                            <div class="chart-card-header">
                                <h3 class="chart-title">文章发布热力图(<?php echo date('Y'); ?>)</h3>
                            </div>
                            <div class="chart-container">
                                <canvas id="heatmap-chart"></canvas>
                            </div>
                        </div>
                    </div>
                    <!-- 归档列表 -->
                    <div class="archive-section">
                        <div class="archive-title">
                            <span>文章归档</span>
                            <button class="expand-all-button" id="expand-all-btn">展开全部</button>
                        </div>
                        <div id="archives-container">
                            <?php 
                            if (!empty($posts_by_year)):
                                foreach ($posts_by_year as $year => $year_data): 
                                    $months = $year_data['months'];
                            ?>
                                <div class="archive-year" data-year="<?php echo $year; ?>">
                                    <div class="year-header" onclick="toggleYear(<?php echo $year; ?>)">
                                        <span class="year-title"><?php echo $year; ?>年</span>
                                        <span class="year-count"><?php echo $year_data['count']; ?>篇</span>
                                    </div>
                                    <div class="year-content" id="year-<?php echo $year; ?>" style="display: none;">
                                        <?php foreach ($months as $month => $month_data): ?>
                                            <div class="month-section">
                                                <div class="month-header" onclick="toggleMonth('<?php echo $year.'-'.$month; ?>')">
                                                    <?php echo $month_data['name']; ?> (<?php echo count($month_data['posts']); ?>篇)
                                                    <i class="fa fa-angle-down toggle-icon"></i>
                                                </div>
                                                <div class="post-list" id="month-<?php echo $year.'-'.$month; ?>">
                                                    <?php foreach ($month_data['posts'] as $post): ?>
                                                        <div class="post-item">
                                                            <div class="post-date"><?php echo date('m-d', strtotime($post['date'])); ?></div>
                                                            <div class="post-title">
                                                                <a href="<?php echo esc_url($post['permalink']); ?>" title="<?php echo esc_attr($post['title']); ?>">
                                                                    <?php echo esc_html($post['title']); ?>
                                                                </a>
                                                            </div>
                                                        </div>
                                                    <?php endforeach; ?>
                                                </div>
                                            </div>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php 
                                endforeach;
                            endif; 
                            ?>
                        </div>
                    </div>
                </article>
            </div>
            <?php comments_template('/template/comments.php', true); ?>
        </div>
    </div>
</main>

<!-- 归档列表交互及主题切换监听 -->
<script>
document.addEventListener('DOMContentLoaded', function() {
    // 归档交互
    window.toggleYear = function(year) {
        const yearContent = document.getElementById('year-' + year);
        yearContent.style.display = (yearContent.style.display === 'none' || yearContent.style.display === '') ? 'block' : 'none';
    };
    window.toggleMonth = function(monthId) {
        const monthContent = document.getElementById('month-' + monthId);
        const header = monthContent.previousElementSibling;
        const icon = header.querySelector('.toggle-icon');
        if (monthContent.style.display === 'block') {
            monthContent.style.display = 'none';
            icon.classList.remove('open');
        } else {
            monthContent.style.display = 'block';
            icon.classList.add('open');
        }
    };
    // 展开/收起所有归档
    document.getElementById('expand-all-btn').addEventListener('click', function() {
        const yearContents = document.querySelectorAll('.year-content');
        const postLists = document.querySelectorAll('.post-list');
        const icons = document.querySelectorAll('.toggle-icon');
        const btn = this;
        if (btn.getAttribute('data-expanded') === 'true') {
            yearContents.forEach(el => el.style.display = 'none');
            postLists.forEach(el => el.style.display = 'none');
            icons.forEach(icon => icon.classList.remove('open'));
            btn.textContent = '展开全部';
            btn.setAttribute('data-expanded', 'false');
        } else {
            yearContents.forEach(el => el.style.display = 'block');
            postLists.forEach(el => el.style.display = 'block');
            icons.forEach(icon => icon.classList.add('open'));
            btn.textContent = '收起全部';
            btn.setAttribute('data-expanded', 'true');
        }
    });
    // 防抖函数:延迟执行,避免频繁调用
    function debounce(fn, delay) {
        let timer = null;
        return function() {
            clearTimeout(timer);
            timer = setTimeout(fn, delay);
        }
    }
    // 防抖后的图表初始化
    const debouncedInitCharts = debounce(function() {
        if (typeof initCharts === 'function') {
            initCharts();
        }
    }, 200);
    // 当前主题状态,仅在深色/浅色切换时触发图表更新
    let currentTheme = document.body.classList.contains('dark') ? 'dark' : 'light';
    
    // 3D动画效果鼠标跟踪 - 开始
    const square = document.getElementById('square');
    if (square) {
        document.addEventListener('mousemove', function(e) {
            square.style.left = e.clientX + 'px';
            square.style.top = e.clientY + 'px';
        });
    }
    // 3D动画效果鼠标跟踪 - 结束
});
</script>

<!-- 图表初始化与配置 -->
<script type="text/javascript">
function initCharts() {
    const isDark = document.body.classList.contains('dark');
    const textColor = isDark ? '#e0e0e0' : '#333333';
    const gridColor = isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.07)';
    // 文章分类统计饼图
    const categoryCtx = document.getElementById('category-chart').getContext('2d');
    if (window.categoryChart) window.categoryChart.destroy();
    window.categoryChart = new Chart(categoryCtx, {
        type: 'doughnut',
        data: {
            labels: archivesData.categoryData.map(item => item.name),
            datasets: [{
                data: archivesData.categoryData.map(item => item.value),
                backgroundColor: [
                    '#3498db', '#2ecc71', '#f1c40f', '#e74c3c', '#9b59b6',
                    '#1abc9c', '#e67e22', '#95a5a6', '#34495e', '#16a085',
                    '#2980b9', '#27ae60', '#f39c12', '#c0392b', '#8e44ad'
                ]
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: {
                    position: 'right',
                    labels: {
                        color: textColor,
                        font: { size: 12 }
                    }
                },
                tooltip: {
                    backgroundColor: isDark ? '#333' : '#fff',
                    titleColor: isDark ? '#fff' : '#333',
                    bodyColor: isDark ? '#fff' : '#333'
                }
            }
        }
    });
    // 用户类型分布饼图
    const userCtx = document.getElementById('user-chart').getContext('2d');
    if (window.userChart) window.userChart.destroy();
    window.userChart = new Chart(userCtx, {
        type: 'doughnut',
        data: {
            labels: archivesData.userVipData.map(item => item.name),
            datasets: [{
                data: archivesData.userVipData.map(item => item.value),
                backgroundColor: ['#3498db', '#2ecc71', '#f1c40f']
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: {
                    position: 'right',
                    labels: {
                        color: textColor,
                        font: { size: 12 }
                    }
                },
                tooltip: {
                    backgroundColor: isDark ? '#333' : '#fff',
                    titleColor: isDark ? '#fff' : '#333',
                    bodyColor: isDark ? '#fff' : '#333'
                }
            }
        }
    });
    // 月度文章发布量折线图
    const monthlyCtx = document.getElementById('monthly-chart').getContext('2d');
    if (window.monthlyChart) window.monthlyChart.destroy();
    window.monthlyChart = new Chart(monthlyCtx, {
        type: 'line',
        data: {
            labels: archivesData.monthlyData.months,
            datasets: [{
                label: '文章发布量',
                data: archivesData.monthlyData.counts,
                borderColor: '#3498db',
                backgroundColor: 'rgba(52,152,219,0.1)',
                fill: true,
                tension: 0.3
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            scales: {
                x: {
                    ticks: {
                        color: textColor,
                        autoSkip: true,
                        maxTicksLimit: 12,
                        callback: function(value, index, values) {
                            return index % 2 === 0 ? this.getLabelForValue(value) : '';
                        },
                        minRotation: 45,
                        maxRotation: 45
                    },
                    grid: { color: gridColor }
                },
                y: {
                    ticks: { color: textColor },
                    grid: { color: gridColor }
                }
            },
            plugins: {
                legend: { labels: { color: textColor } },
                tooltip: {
                    backgroundColor: isDark ? '#333' : '#fff',
                    titleColor: isDark ? '#fff' : '#333',
                    bodyColor: isDark ? '#fff' : '#333'
                }
            }
        }
    });
    // 文章发布热力图柱状图
    const heatmapLabels = archivesData.heatmapData.map(item => item[0]);
    const heatmapCounts = archivesData.heatmapData.map(item => item[1]);
    const heatmapCtx = document.getElementById('heatmap-chart').getContext('2d');
    if (window.heatmapChart) window.heatmapChart.destroy();
    window.heatmapChart = new Chart(heatmapCtx, {
        type: 'bar',
        data: {
            labels: heatmapLabels,
            datasets: [{
                label: '每日文章数',
                data: heatmapCounts,
                backgroundColor: '#2ecc71'
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            scales: {
                x: {
                    ticks: {
                        color: textColor,
                        autoSkip: true,
                        maxTicksLimit: 10,
                        minRotation: 45,
                        maxRotation: 45,
                        callback: function(value, index, values) {
                            return index % 2 === 0 ? this.getLabelForValue(value) : '';
                        }
                    },
                    grid: { color: gridColor }
                },
                y: {
                    ticks: { color: textColor },
                    grid: { color: gridColor }
                }
            },
            plugins: {
                legend: { display: false },
                tooltip: {
                    backgroundColor: isDark ? '#333' : '#fff',
                    titleColor: isDark ? '#fff' : '#333',
                    bodyColor: isDark ? '#fff' : '#333'
                }
            }
        }
    });
}
document.addEventListener('DOMContentLoaded', function() {
    initCharts();
});
</script>

<?php
get_footer();
?>

 

请登录后发表评论