archive.php11.8 KB
<?php
// 1. 引入配置文件并连接数据库
if (!file_exists(__DIR__ . '/config.php')) {
die('系统未安装!请先访问 <a href="install/">安装向导</a>');
}
require __DIR__ . '/config.php';
try {
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4";
$pdo = new PDO($dsn, DB_USER, DB_PASS, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
} catch (PDOException $e) {
die("数据库连接失败:" . $e->getMessage());
}
// --- 1. 统计数据 ---
$stats = [
'posts' => $pdo->query("SELECT COUNT(*) FROM posts")->fetchColumn(),
'comments' => $pdo->query("SELECT COUNT(*) FROM comments WHERE status='approved'")->fetchColumn(),
'links' => $pdo->query("SELECT COUNT(*) FROM links")->fetchColumn(),
'tags' => $pdo->query("SELECT COUNT(*) FROM tags")->fetchColumn()
];
// --- 2. 标签统计 ---
$tags = $pdo->query("
SELECT t.name, COUNT(pt.post_id) as count
FROM tags t LEFT JOIN post_tags pt ON t.id = pt.tag_id
GROUP BY t.id ORDER BY count DESC
")->fetchAll(PDO::FETCH_ASSOC);
// --- 3. 按年份分组数据 (用于默认视图) ---
// 获取所有有文章的年份
$years_data = $pdo->query("SELECT YEAR(created_at) as year, COUNT(*) as count FROM posts GROUP BY year ORDER BY year DESC")->fetchAll();
// --- 4. 按月份分组数据 (用于切换视图) ---
// 获取所有有文章的年月
$months_data = $pdo->query("
SELECT YEAR(created_at) as year, MONTH(created_at) as month, COUNT(*) as count
FROM posts GROUP BY year, month ORDER BY year DESC, month DESC
")->fetchAll();
// --- 5. 辅助函数:获取指定时间段的文章列表 ---
function getPostsByTime($pdo, $year, $month = null) {
if ($month) {
$sql = "SELECT id, title, created_at FROM posts WHERE YEAR(created_at)=:y AND MONTH(created_at)=:m ORDER BY created_at DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute([':y' => $year, ':m' => $month]);
} else {
$sql = "SELECT id, title, created_at FROM posts WHERE YEAR(created_at)=:y ORDER BY created_at DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute([':y' => $year]);
}
return $stmt->fetchAll();
}
$page_title = "文章归档"; // 用于在 header 中显示标题
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文章归档 - 我的 PHP 博客</title>
<style>
/* 基础样式变量 */
:root {
--primary-color: #d68c6e; /* 类似截图的暖棕色 */
--bg-color: #fdfbf7; /* 米白色背景 */
--card-bg: #ffffff;
--text-main: #333333;
--text-sub: #888888;
--border-color: #eeeeee;
}
/* 1. 顶部统计卡片 */
.gd-stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin-bottom: 5px; }
.gd-stat-card { background: var(--card-bg); padding: 20px; border-radius: 12px; text-align: center; box-shadow: 0 2px 10px rgba(0,0,0,0.03); }
.stat-num { font-size: 24px; font-weight: bold; color: var(--text-main); display: block; margin-bottom: 5px; }
.stat-label { font-size: 12px; color: var(--text-sub); }
/* 2. 标签云 */
.section-box { background: var(--card-bg); border-radius: 12px; padding: 25px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.03); }
.tag-cloud { display: flex; flex-wrap: wrap; gap: 10px; }
.tag-item { display: flex; align-items: center; justify-content: space-between; background: #f9f9f9; padding: 8px 15px; border-radius: 6px; min-width: 120px; text-decoration: none; color: var(--text-main); transition: 0.2s; }
.tag-item:hover { background: var(--primary-color); color: white; }
.tag-count { background: rgba(0,0,0,0.05); padding: 2px 6px; border-radius: 4px; font-size: 12px; }
.tag-item:hover .tag-count { background: rgba(255,255,255,0.2); color: white; }
/* 3. 归档控制栏 */
.archive-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0px; }
.view-switcher { display: flex; background: #eee; padding: 4px; border-radius: 8px; }
.switch-btn { border: none; background: transparent; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-size: 14px; color: var(--text-sub); transition: 0.3s; }
.switch-btn.active { background: var(--primary-color); color: white; box-shadow: 0 2px 5px rgba(214, 140, 110, 0.3); }
/* 4. 归档列表容器 */
.archive-group { background: var(--card-bg); border-radius: 12px; margin-bottom: 15px; overflow: hidden; border: 1px solid var(--border-color); }
/* 折叠标题栏 */
.group-title { padding: 15px 25px; display: flex; justify-content: space-between; align-items: center; cursor: pointer; background: #fff; user-select: none; }
.group-title:hover { background: #fafafa; }
.title-left { font-weight: bold; font-size: 18px; display: flex; align-items: center; }
.arrow { display: inline-block; width: 0; height: 0; border-top: 6px solid transparent; border-bottom: 6px solid transparent; border-left: 8px solid #999; margin-right: 10px; transition: transform 0.3s; }
.group-title.open .arrow { transform: rotate(90deg); }
.count-badge { background: #f0f0f0; padding: 4px 10px; border-radius: 20px; font-size: 12px; color: #666; }
/* 文章内容区 (双列布局) */
.post-list-container { display: none; padding: 10px 25px 25px; border-top: 1px dashed var(--border-color); }
.group-title.open + .post-list-container { display: block; } /* 核心:配合JS实现展开 */
.post-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px 40px; } /* 双列布局 */
.post-item { display: flex; align-items: baseline; padding: 8px 0; border-bottom: 1px solid #f5f5f5; }
.post-date { color: var(--primary-color); font-weight: bold; margin-right: 15px; min-width: 45px; font-family: monospace; font-size: 14px;}
.post-link { text-decoration: none; color: var(--text-main); font-size: 15px; line-height: 1.4; transition: color 0.2s; }
.post-link:hover { color: var(--primary-color); }
/* 响应式:手机端变单列 */
@media (max-width: 600px) {
.gd-stats-grid { grid-template-columns: repeat(2, 1fr); }
.post-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<!-- 搜索弹窗 -->
<?php require_once __DIR__ . '/search-tc.php'; ?>
<div class="container">
<?php require_once __DIR__ . '/header.php'; ?>
<div class="main-content">
<div class="content-left">
<!-- 顶部统计 -->
<div class="gd-stats-grid">
<div class="stat-card"><span class="stat-num"><?php echo $stats['posts']; ?></span><span class="stat-label">文章总数</span></div>
<div class="stat-card"><span class="stat-num"><?php echo $stats['comments']; ?></span><span class="stat-label">评论总数</span></div>
<div class="stat-card"><span class="stat-num"><?php echo $stats['tags']; ?></span><span class="stat-label">标签总数</span></div>
<div class="stat-card"><span class="stat-num"><?php echo $stats['links']; ?></span><span class="stat-label">友链总数</span></div>
</div>
<!-- 标签统计 -->
<div class="section-box">
<h3 style="margin-top:0; font-size:16px; color:#666;">标签统计</h3>
<div class="tag-cloud">
<?php foreach ($tags as $tag): ?>
<a href="#" class="tag-item">
<span><?php echo htmlspecialchars($tag['name']); ?></span>
<span class="tag-count"><?php echo $tag['count']; ?> 篇</span>
</a>
<?php endforeach; ?>
</div>
</div>
<!-- 归档控制 -->
<div class="archive-header">
<div></div> <!-- 占位 -->
<div class="view-switcher">
<button class="switch-btn active" onclick="switchView('year')">按年份</button>
<button class="switch-btn" onclick="switchView('month')">按月份</button>
</div>
</div>
<!-- ======================= 视图 A: 按年份 (默认) ======================= -->
<div id="view-year">
<?php foreach ($years_data as $yearRow):
$year = $yearRow['year'];
$yearCount = $yearRow['count'];
$yearPosts = getPostsByTime($pdo, $year); // 获取该年文章
?>
<div class="archive-group">
<div class="group-title open" onclick="toggleGroup(this)">
<div class="title-left"><span class="arrow"></span><?php echo $year; ?> 年</div>
<div class="count-badge"><?php echo $yearCount; ?> 篇文章</div>
</div>
<div class="post-list-container">
<div class="post-grid">
<?php foreach ($yearPosts as $post): ?>
<div class="post-item">
<span class="post-date"><?php echo date('m-d', strtotime($post['created_at'])); ?></span>
<a href="post.php?id=<?php echo $post['id']; ?>" class="post-link"><?php echo htmlspecialchars($post['title']); ?></a>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<!-- ======================= 视图 B: 按月份 (隐藏) ======================= -->
<div id="view-month" style="display: none;">
<?php foreach ($months_data as $monthRow):
$year = $monthRow['year'];
$month = $monthRow['month'];
$monthCount = $monthRow['count'];
$monthPosts = getPostsByTime($pdo, $year, $month); // 获取该月文章
?>
<div class="archive-group">
<div class="group-title open" onclick="toggleGroup(this)">
<div class="title-left"><span class="arrow"></span><?php echo $year; ?> 年 <?php echo str_pad($month, 2, '0', STR_PAD_LEFT); ?> 月</div>
<div class="count-badge"><?php echo $monthCount; ?> 篇文章</div>
</div>
<div class="post-list-container">
<div class="post-grid">
<?php foreach ($monthPosts as $post): ?>
<div class="post-item">
<span class="post-date"><?php echo date('d', strtotime($post['created_at'])); ?></span>
<a href="post.php?id=<?php echo $post['id']; ?>" class="post-link"><?php echo htmlspecialchars($post['title']); ?></a>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php require_once __DIR__ . '/sidebar-right.php'; ?>
</div>
<!-- 【结构优化】将 footer 移出 container,使其能够横跨整个屏幕宽度 -->
<?php require_once __DIR__ . '/footer.php'; ?>
</div>
<script>
// 切换 年份/月份 视图
function switchView(type) {
const viewYear = document.getElementById('view-year');
const viewMonth = document.getElementById('view-month');
const btns = document.querySelectorAll('.switch-btn');
if (type === 'year') {
viewYear.style.display = 'block';
viewMonth.style.display = 'none';
btns[0].classList.add('active');
btns[1].classList.remove('active');
} else {
viewYear.style.display = 'none';
viewMonth.style.display = 'block';
btns[0].classList.remove('active');
btns[1].classList.add('active');
}
}
// 点击标题折叠/展开
function toggleGroup(element) {
element.classList.toggle('open');
// 注意:CSS中使用了 .group-title.open + .post-list-container 来控制显示
// 所以这里只需要切换 class 即可,不需要操作 display
}
</script>
</body>
</html>