init: 我的博客项目
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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"]);
|
||||
}
|
||||
@@ -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");
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user