init: 我的博客项目

This commit is contained in:
Your Name
2026-09-09 19:30:18 +08:00
commit 76c241f032
34 changed files with 3420 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+42
View File
@@ -0,0 +1,42 @@
<?php
if (session_status() === PHP_SESSION_NONE) { session_start(); }
function current_user() {
if (!empty($_SESSION["user_id"])) {
$st = db()->prepare("SELECT * FROM users WHERE id=?");
$st->execute([$_SESSION["user_id"]]);
return $st->fetch();
}
return null;
}
function is_login() {
return !empty($_SESSION["user_id"]);
}
function is_admin() {
$u = current_user();
return $u && $u["role"] === "admin";
}
function require_admin() {
if (!is_admin()) {
header("Location: " . SITE_URL . "login.php");
exit;
}
}
function attempt_login($username, $password) {
$st = db()->prepare("SELECT * FROM users WHERE username=?");
$st->execute([$username]);
$user = $st->fetch();
if ($user && password_verify($password, $user["password_hash"])) {
$_SESSION["user_id"] = $user["id"];
return true;
}
return false;
}
function logout() {
unset($_SESSION["user_id"]);
}
+16
View File
@@ -0,0 +1,16 @@
<?php
define("SITE_NAME", "我的博客");
define("SITE_DESC", "欢迎访问");
define("SITE_URL", "/myblog/");
define("UPLOAD_DIR", __DIR__ . "/../uploads/");
define("DB_HOST", "127.0.0.1");
define("DB_NAME", "myblog");
define("DB_USER", "root");
define("DB_PASS", "root");
define("DB_CHARSET", "utf8mb4");
error_reporting(E_ALL);
ini_set("display_errors", "1");
date_default_timezone_set("Asia/Shanghai");
+19
View File
@@ -0,0 +1,19 @@
<?php
require_once __DIR__ . "/config.php";
function db() {
static $pdo = null;
if ($pdo === null) {
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
try {
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
} catch (PDOException $e) {
die("数据库连接失败: " . htmlspecialchars($e->getMessage()));
}
}
return $pdo;
}
+8
View File
@@ -0,0 +1,8 @@
</main>
<?php include __DIR__ . "/sidebar.php"; ?>
</div>
</div>
<div class="footnote"><?php echo e(SITE_NAME); ?> · 用心记录生活</div>
<script src="<?php echo e(SITE_URL); ?>assets/js/main.js"></script>
</body>
</html>
+62
View File
@@ -0,0 +1,62 @@
<?php
require_once __DIR__ . "/db.php";
function e($str) {
return htmlspecialchars((string)$str, ENT_QUOTES, "UTF-8");
}
function slugify($text) {
$text = strtolower(trim($text));
$text = preg_replace("/[^a-z0-9]+/", "-", $text);
$text = trim($text, "-");
return $text !== "" ? $text : "post-" . uniqid();
}
function get_categories() {
return db()->query("SELECT * FROM categories ORDER BY id")->fetchAll();
}
function get_all_tags() {
return db()->query("SELECT t.*, COUNT(at.article_id) cnt FROM tags t LEFT JOIN article_tags at ON t.id=at.tag_id GROUP BY t.id ORDER BY cnt DESC")->fetchAll();
}
function get_article_tags($articleId) {
$st = db()->prepare("SELECT t.* FROM tags t JOIN article_tags at ON t.id=at.tag_id WHERE at.article_id=?");
$st->execute([$articleId]);
return $st->fetchAll();
}
function get_archives() {
$sql = "SELECT DATE_FORMAT(created_at, ?) ym, COUNT(*) cnt FROM articles WHERE status=? GROUP BY ym ORDER BY ym DESC";
$st = db()->prepare($sql);
$st->execute(["%Y年%m月", "published"]);
return $st->fetchAll();
}
function record_visit($page) {
$ip = $_SERVER["REMOTE_ADDR"] ?? "";
$ua = substr($_SERVER["HTTP_USER_AGENT"] ?? "", 0, 250);
$st = db()->prepare("INSERT IGNORE INTO visitor_stats (visit_date, ip, page, ua) VALUES (CURDATE(), ?, ?, ?)");
$st->execute([$ip, $page, $ua]);
}
function paginate($total, $page, $perPage) {
$pages = max(1, (int)ceil($total / $perPage));
$page = max(1, min($pages, (int)$page));
return [
"page" => $page,
"pages" => $pages,
"offset" => ($page - 1) * $perPage,
"perPage" => $perPage,
];
}
function markdown($text) {
static $parsedown = null;
if ($parsedown === null) {
require_once __DIR__ . "/Parsedown.php";
$parsedown = new Parsedown();
$parsedown->setBreaksEnabled(true);
}
return $parsedown->text((string)$text);
}
+41
View File
@@ -0,0 +1,41 @@
<?php
require_once __DIR__ . "/config.php";
require_once __DIR__ . "/functions.php";
require_once __DIR__ . "/auth.php";
$curPage = isset($pageName) ? $pageName : "";
$navCats = get_categories();
$navTags = get_all_tags();
$navArch = get_archives();
?>
<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo isset($pageTitle) ? e($pageTitle) . " - " . SITE_NAME : SITE_NAME; ?></title>
<meta name="description" content="<?php echo e(SITE_DESC); ?>">
<link rel="stylesheet" href="<?php echo e(SITE_URL); ?>assets/css/style.css">
</head>
<body>
<div class="bg"></div>
<nav class="glass-nav">
<div class="nav-brand"><a href="<?php echo e(SITE_URL); ?>index.php">我的博客</a></div>
<div class="nav-links">
<a class="nav-link<?php echo $curPage==="index"?" active":""; ?>" href="<?php echo e(SITE_URL); ?>index.php">首页</a>
<?php foreach ($navCats as $c) { ?>
<a class="nav-link<?php echo isset($curCategory) && $curCategory==$c["id"]?" active":""; ?>" href="<?php echo e(SITE_URL); ?>category.php?id=<?php echo (int)$c["id"]; ?>"><?php echo e($c["name"]); ?></a>
<?php } ?>
<a class="nav-link<?php echo $curPage==="archive"?" active":""; ?>" href="<?php echo e(SITE_URL); ?>archive.php">归档</a>
<a class="nav-link<?php echo $curPage==="about"?" active":""; ?>" href="<?php echo e(SITE_URL); ?>about.php">关于</a>
<button class="theme-toggle" id="themeBtn">深色模式</button>
<?php if (is_login()) { ?>
<a class="glass-btn primary" href="<?php echo e(SITE_URL); ?>admin/index.php">管理</a>
<a class="glass-btn primary" href="<?php echo e(SITE_URL); ?>logout.php">退出</a>
<?php } else { ?>
<a class="glass-btn primary" href="<?php echo e(SITE_URL); ?>login.php">登录</a>
<?php } ?>
</div>
</nav>
<div class="container">
<div class="layout">
<main>
+26
View File
@@ -0,0 +1,26 @@
<aside class="sidebar">
<div class="side-panel glass">
<h3>热门标签</h3>
<div class="chip-row">
<?php foreach ($navTags as $t) { ?>
<a class="glass-chip" href="<?php echo e(SITE_URL); ?>tag.php?id=<?php echo (int)$t["id"]; ?>"><?php echo e($t["name"]); ?></a>
<?php } ?>
</div>
</div>
<div class="side-panel glass">
<h3>分类</h3>
<div class="chip-row">
<?php foreach ($navCats as $c) { ?>
<a class="glass-chip" href="<?php echo e(SITE_URL); ?>category.php?id=<?php echo (int)$c["id"]; ?>"><?php echo e($c["name"]); ?></a>
<?php } ?>
</div>
</div>
<div class="side-panel glass">
<h3>归档</h3>
<div id="archRow">
<?php foreach ($navArch as $a) { ?>
<div class="arch-item"><a href="<?php echo e(SITE_URL); ?>archive.php?ym=<?php echo e($a["ym"]); ?>"><?php echo e($a["ym"]); ?></a><span><?php echo (int)$a["cnt"]; ?> 篇</span></div>
<?php } ?>
</div>
</div>
</aside>