04-25-周六_15-46-07

This commit is contained in:
AaronXu
2026-04-25 15:46:08 +08:00
parent d9491577b5
commit 33871fe9d6
21 changed files with 4319 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
<?php
$pageTitle = '网站后台管理 - 添加文章';
$page = 'articles';
include("header.php");
?>
<?php
if (isset($_REQUEST["title"])) {
// 连接数据库
include("db.php");
// 接收标题,作者,内容等数据
$title = $_REQUEST["title"];
$author = $_REQUEST["author"];
$content = $_REQUEST["content"];
// 设置为+8时区读取系统时间
date_default_timezone_set('PRC');
$time = date("Y-m-d H:i:s");
// 插入数据库
$sql = "INSERT INTO articles (title, author, content, time) VALUES ('$title', '$author', '$content', '$time')";
if (mysqli_query($conn, $sql) === TRUE) {
echo "<script>alert('文章添加成功');location.href='articles_list.php'</script>";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
}
?>
<main class="main-content">
<div class="page-header">
<h2>添加文章</h2>
<p>编写博客的文章</p>
</div>
<div class="form-card">
<form action="" method="post">
<div class="form-group">
<label for="title">文章标题</label>
<input type="text" id="title" name="title" placeholder="请输入文章标题" required>
</div>
<div class="form-group">
<label for="author">文章作者</label>
<input type="text" id="author" name="author" placeholder="请输入文章作者" required>
</div>
<div class="form-group">
<label for="content">文章内容</label>
<textarea id="content" name="content" placeholder="请输入文章内容" required></textarea>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary">提交</button>
<a href="articles_list.php" class="btn btn-secondary">返回文章列表</a>
</div>
</form>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,73 @@
<?php
$pageTitle = '网站后台管理 - 修改文章';
$page = 'articles';
include("header.php");
?>
<?php
// 连接数据库
include("db.php");
// 接收文章ID
$id = $_REQUEST["id"];
if (isset($_POST["title"])) {
// 接收标题,作者,内容等数据
$title = $_POST["title"];
$author = $_POST["author"];
$content = $_POST["content"];
// 设置为+8时区读取系统时间
date_default_timezone_set('PRC');
$time = date("Y-m-d H:i:s");
// 插入数据库
$sql = "update articles set title='$title', author='$author', content='$content', time='$time' where id='$id'";
if (mysqli_query($conn, $sql) === TRUE) {
echo "<script>alert('文章添加成功');location.href='articles_list.php'</script>";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
}
?>
<main class="main-content">
<div class="page-header">
<h2>修改文章</h2>
<p>修改博客的文章</p>
</div>
<?php
// 以及对应的内容
$sql = "select * from articles where id = $id";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);
?>
<div class="form-card">
<form action="" method="post">
<div class="form-group">
<label for="title">文章标题</label>
<input type="text" id="title" name="title" placeholder="请输入文章标题" value="<?php echo $row["title"]; ?>" required>
</div>
<div class="form-group">
<label for="author">文章作者</label>
<input type="text" id="author" name="author" placeholder="请输入文章作者" value="<?php echo $row["author"]; ?>" required>
</div>
<div class="form-group">
<label for="content">文章内容</label>
<textarea id="content" name="content" placeholder="请输入文章内容" required><?php echo $row["content"]; ?></textarea>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary">提交</button>
<a href="articles_list.php" class="btn btn-secondary">返回文章列表</a>
</div>
</form>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,73 @@
<?php
$pageTitle = '网站后台管理 - 文章列表';
$page = 'articles';
include("header.php");
?>
<main class="main-content">
<div class="page-header page-header-bar">
<div>
<h2>文章管理</h2>
<p>管理博客的文章</p>
</div>
<a href="article_add.php" class="btn-add">
<span>+</span>
<span>添加文章</span>
</a>
</div>
<div class="table-container">
<table class="articles-table">
<thead>
<tr>
<th>序号</th>
<th>标题</th>
<th>作者</th>
<th>发布时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php
// 连接数据库
include("db.php");
// 删除文章的功能
if(isset($_REQUEST["del"])){
$id = $_REQUEST["id"];
$sql = "delete from articles where id = '$id'";
if (mysqli_query($conn, $sql) === TRUE) {
echo "<script>alert('文章删除成功');location.href='articles_list.php'</script>";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
}
// 查询所有文章
$sql = "select * from articles";
$result = mysqli_query($conn, $sql);
while ($row = mysqli_fetch_assoc($result)) {
// 标题超过10个字就加省略号
$title = strlen($row["title"]) > 45 ? substr($row["title"], 0, 45) . "..." : $row["title"];
?>
<tr>
<td><?php echo $row["id"];?></td>
<td><?php echo $title;?></td>
<td><?php echo $row["author"];?></td>
<td><?php echo $row["time"];?></td>
<td>
<div class="action-btns">
<a href="article_edit.php?id=<?php echo $row["id"];?>" class="btn btn-edit">✏️ 编辑</a>
<a href="?del&id=<?php echo $row["id"];?>" class="btn btn-delete" onclick="return confirm('确定要删除该文章吗?')">🗑️ 删除</a>
</div>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,73 @@
<?php
$pageTitle = '网站后台管理 - 文章列表';
$page = 'commonts';
include("header.php");
?>
<main class="main-content">
<div class="page-header page-header-bar">
<div>
<h2>评论管理</h2>
<p>管理博客的评论</p>
</div>
</div>
<div class="table-container">
<table class="articles-table">
<thead>
<tr>
<th>序号</th>
<th>文章</th>
<th>昵称</th>
<th>发布时间</th>
<th>内容</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php
// 连接数据库
include("db.php");
// 删除文章的功能
if(isset($_REQUEST["del"])){
$id = $_REQUEST["id"];
$sql = "delete from comments where id = '$id'";
if (mysqli_query($conn, $sql) === TRUE) {
echo "<script>location.href='comment_list.php'</script>";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
}
// 查询所有评论
$sql = "select * from comments order by id desc";
$result = mysqli_query($conn, $sql);
while ($row = mysqli_fetch_assoc($result)) {
$sql = "select * from articles where id = '". $row['article_id']. "'";
$article_result = mysqli_query($conn, $sql);
$article_row = mysqli_fetch_assoc($article_result);
$article_title = $article_row["title"];
?>
<tr>
<td><?php echo $row["id"];?></td>
<td><?php echo $article_title;?></td>
<td><?php echo $row["nick"];?></td>
<td><?php echo $row["time"];?></td>
<td><?php echo $row["content"];?></td>
<td>
<div class="action-btns">
<a href="?del&id=<?php echo $row["id"];?>" class="btn btn-delete" onclick="return confirm('确定要删除该文章吗?')">🗑️ 删除</a>
</div>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,16 @@
<?php
// 连接数据库
$host = "127.0.0.1";
$dbname = "root";
$dbpassword = "usbw";
$database = "blog";
$port = 3307;
$conn = mysqli_connect($host, $dbname, $dbpassword, $database, $port);
if (!$conn) {
echo "连接失败";
exit;
}
// 设置连接的字符集为utf8
mysqli_query($conn,"set names utf8");

View File

@@ -0,0 +1,708 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<?php
session_start();
if (!isset($_SESSION["username"])) {
echo "<script>alert('请先登录');location.href='login.php'</script>";
exit;
}
$page = isset($page) ? $page : '';
$pageTitle = isset($pageTitle) ? $pageTitle : '网站后台管理';
if (isset($_GET["logout"])) {
session_destroy();
echo "<script>alert('退出成功');location.href='login.php'</script>";
}
?>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $pageTitle; ?></title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'PingFang SC', 'Microsoft YaHei', 'Segoe UI', Arial, sans-serif;
background: #fafbfc;
color: #374151;
min-height: 100vh;
letter-spacing: 0.3px;
line-height: 1.6;
}
/* 顶部导航 */
.header {
background: #ffffff;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32px;
border-bottom: 1px solid #e5e7eb;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
.header h1 {
font-size: 18px;
color: #1f2937;
font-weight: 600;
letter-spacing: 1px;
}
.header .user-info {
display: flex;
align-items: center;
gap: 10px;
color: #6b7280;
font-size: 14px;
}
.header .user-avatar {
width: 34px;
height: 34px;
border-radius: 50%;
background: #3b82f6;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
font-size: 13px;
}
/* 侧边栏 */
.sidebar {
width: 220px;
background: #ffffff;
color: #374151;
position: fixed;
left: 0;
top: 60px;
bottom: 0;
padding: 20px 0;
border-right: 1px solid #e5e7eb;
display: flex;
flex-direction: column;
}
.sidebar a {
display: flex;
align-items: center;
gap: 14px;
color: #6b7280;
text-decoration: none;
padding: 12px 24px;
font-size: 14px;
transition: all 0.2s ease;
margin: 4px 12px;
border-radius: 8px;
letter-spacing: 0.5px;
}
.sidebar a:hover {
background: #f3f4f6;
color: #374151;
}
.sidebar a.active {
background: #eff6ff;
color: #3b82f6;
font-weight: 500;
}
.sidebar a .icon {
font-size: 17px;
width: 22px;
text-align: center;
}
/* 退出登录 */
.sidebar .logout {
margin-top: auto;
border-top: 1px solid #e5e7eb;
padding-top: 16px;
margin-left: 0;
margin-right: 0;
}
.sidebar .logout:hover {
background: #fef2f2;
color: #ef4444;
}
/* 主内容区 */
.main-content {
margin-left: 220px;
margin-top: 60px;
padding: 32px 40px;
min-height: calc(100vh - 60px);
}
/* 欢迎区域main.php */
.welcome-section {
margin-bottom: 28px;
}
.welcome-section h2 {
font-size: 24px;
color: #111827;
margin-bottom: 6px;
font-weight: 600;
letter-spacing: 0.5px;
}
.welcome-section p {
color: #9ca3af;
font-size: 14px;
letter-spacing: 0.5px;
}
/* 统计卡片main.php */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
margin-bottom: 28px;
}
.stat-card {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 24px;
transition: all 0.25s ease;
}
.stat-card:hover {
border-color: #d1d5db;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04);
}
.stat-card .card-icon {
width: 44px;
height: 44px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
margin-bottom: 16px;
}
.stat-card.visitors .card-icon {
background: #eff6ff;
}
.stat-card.memory .card-icon {
background: #ecfdf5;
}
.stat-card.cpu .card-icon {
background: #fef3c7;
}
.stat-card.site .card-icon {
background: #fef2f2;
}
.stat-card .stat-label {
font-size: 13px;
color: #9ca3af;
margin-bottom: 6px;
letter-spacing: 0.5px;
}
.stat-card .stat-value {
font-size: 28px;
font-weight: 600;
color: #111827;
letter-spacing: 0.5px;
}
.stat-card .stat-unit {
font-size: 14px;
color: #6b7280;
font-weight: normal;
}
/* 内容卡片main.php */
.content-card {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 28px;
margin-bottom: 20px;
}
.content-card h3 {
font-size: 16px;
color: #111827;
margin-bottom: 18px;
padding-bottom: 14px;
border-bottom: 1px solid #f3f4f6;
font-weight: 600;
letter-spacing: 0.5px;
}
.info-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
.info-item {
display: flex;
align-items: center;
gap: 14px;
padding: 16px;
background: #f9fafb;
border-radius: 10px;
transition: all 0.2s ease;
}
.info-item:hover {
background: #f3f4f6;
}
.info-item .info-icon {
width: 40px;
height: 40px;
border-radius: 10px;
background: #eff6ff;
color: #3b82f6;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
.info-item .info-text h4 {
font-size: 14px;
color: #374151;
margin-bottom: 2px;
font-weight: 500;
letter-spacing: 0.3px;
}
.info-item .info-text p {
font-size: 13px;
color: #9ca3af;
letter-spacing: 0.3px;
}
/* 页面头部 */
.page-header {
margin-bottom: 28px;
}
.page-header h2 {
font-size: 24px;
color: #111827;
font-weight: 600;
letter-spacing: 0.5px;
margin-bottom: 6px;
}
.page-header p {
color: #9ca3af;
font-size: 14px;
letter-spacing: 0.5px;
}
.page-header-bar {
display: flex;
justify-content: space-between;
align-items: center;
}
.btn-add {
display: inline-flex;
align-items: center;
gap: 8px;
background: #3b82f6;
color: #fff;
padding: 10px 20px;
border-radius: 8px;
text-decoration: none;
font-size: 14px;
font-weight: 500;
transition: all 0.2s ease;
letter-spacing: 0.5px;
}
.btn-add:hover {
background: #2563eb;
}
/* 表格容器 */
.table-container {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 12px;
overflow: hidden;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
thead {
background: #f9fafb;
}
th {
text-align: left;
padding: 16px 20px;
font-size: 13px;
font-weight: 600;
color: #6b7280;
letter-spacing: 0.8px;
border-bottom: 1px solid #e5e7eb;
white-space: nowrap;
}
td {
padding: 14px 16px;
font-size: 14px;
color: #374151;
border-bottom: 1px solid #f3f4f6;
vertical-align: middle;
letter-spacing: 0.3px;
}
tbody tr {
transition: background 0.15s ease;
}
tbody tr:hover {
background: #f9fafb;
}
tbody tr:last-child td {
border-bottom: none;
}
/* 文章列表表格列宽 */
.articles-table th:nth-child(1) {
width: 10%;
}
.articles-table th:nth-child(2) {
width: 30%;
}
.articles-table th:nth-child(3) {
width: 15%;
}
.articles-table th:nth-child(4) {
width: 20%;
}
.articles-table th:nth-child(5) {
width: 25%;
}
.articles-table th:nth-child(6) {
width: 10%;
}
/* 用户列表表格列宽 */
.users-table th:nth-child(1) {
width: 8%;
}
.users-table th:nth-child(2) {
width: 15%;
}
.users-table th:nth-child(3) {
width: 18%;
}
.users-table th:nth-child(4) {
width: 34%;
}
.users-table th:nth-child(5) {
width: 30%;
}
.users-table td:nth-child(1),
.users-table td:nth-child(2),
.users-table td:nth-child(3),
.users-table td:nth-child(4) {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.users-table td:nth-child(5) {
white-space: nowrap;
}
/* 操作按钮 */
.action-btns {
display: flex;
gap: 6px;
}
.btn {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
text-decoration: none;
transition: all 0.15s ease;
letter-spacing: 0.3px;
}
.btn-edit {
background: #eff6ff;
color: #3b82f6;
}
.btn-edit:hover {
background: #3b82f6;
color: #fff;
}
.btn-delete {
background: #fef2f2;
color: #ef4444;
}
.btn-delete:hover {
background: #ef4444;
color: #fff;
}
/* 表单卡片 */
.form-card {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 32px;
max-width: 720px;
}
.form-card-sm {
max-width: 520px;
}
.form-group {
margin-bottom: 24px;
}
.form-group label {
display: block;
font-size: 14px;
font-weight: 500;
color: #374151;
margin-bottom: 8px;
letter-spacing: 0.3px;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 12px 16px;
font-size: 14px;
font-family: inherit;
color: #374151;
background: #ffffff;
border: 1px solid #d1d5db;
border-radius: 8px;
outline: none;
transition: all 0.2s ease;
letter-spacing: 0.3px;
}
.form-group input:focus,
.form-group textarea:focus {
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.form-group input::placeholder,
.form-group textarea::placeholder {
color: #9ca3af;
}
.form-group textarea {
min-height: 240px;
resize: vertical;
line-height: 1.6;
}
.form-hint {
font-size: 13px;
color: #9ca3af;
margin-top: 6px;
}
.btn-group {
display: flex;
gap: 12px;
margin-top: 32px;
}
.btn-group .btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px 24px;
font-size: 14px;
font-weight: 500;
font-family: inherit;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
letter-spacing: 0.5px;
text-decoration: none;
}
.btn-primary {
background: #3b82f6;
color: #fff;
border: none;
}
.btn-primary:hover {
background: #2563eb;
}
.btn-secondary {
background: #ffffff;
color: #374151;
border: 1px solid #d1d5db;
}
.btn-secondary:hover {
background: #f9fafb;
border-color: #9ca3af;
}
/* 密码显示 */
.password-masked {
font-family: inherit;
color: #374151;
letter-spacing: 1px;
}
/* 响应式 */
@media (max-width: 900px) {
.sidebar {
width: 64px;
}
.sidebar .nav-text {
display: none;
}
.sidebar a {
justify-content: center;
padding: 12px;
margin: 4px 8px;
}
.main-content {
margin-left: 64px;
}
}
@media (max-width: 600px) {
.sidebar {
display: none;
}
.main-content {
margin-left: 0;
padding: 24px;
}
.header {
padding: 0 20px;
}
.header h1 {
font-size: 15px;
}
.page-header-bar {
flex-direction: column;
align-items: flex-start;
gap: 14px;
}
th,
td {
padding: 12px 16px;
}
.action-btns {
flex-direction: column;
gap: 6px;
}
.form-card {
padding: 24px;
}
.btn-group {
flex-direction: column;
}
.stats-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<header class="header">
<h1>网站后台管理</h1>
<div class="user-info">
<span>欢迎回来</span>
<div class="user-avatar">管</div>
</div>
</header>
<nav class="sidebar">
<a href="main.php" class="<?php echo $page == 'main' ? 'active' : ''; ?>">
<span class="icon">&#128202;</span>
<span class="nav-text">网站信息</span>
</a>
<a href="articles_list.php" class="<?php echo $page == 'articles' ? 'active' : ''; ?>">
<span class="icon">&#128221;</span>
<span class="nav-text">文章管理</span>
</a>
<a href="comment_list.php" class="<?php echo $page == 'commonts' ? 'active' : ''; ?>">
<span class="icon">&#128172;</span>
<span class="nav-text">评论管理</span>
</a>
<a href="users_list.php" class="<?php echo $page == 'users' ? 'active' : ''; ?>">
<span class="icon">&#128101;</span>
<span class="nav-text">用户管理</span>
</a>
<a href="?logout" class="logout">
<span class="icon">&#128682;</span>
<span class="nav-text">退出登录</span>
</a>
</nav>

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1,719 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>许老师的小站 笔记与随笔</title>
<style>
/* ========== 基础重置 ========== */
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary: #6366f1;
--primary-dark: #4f46e5;
--primary-light: #818cf8;
--accent: #f59e0b;
--bg-page: #f8f9fc;
--bg-card: #ffffff;
--bg-card-hover: #f5f7ff;
--text-primary: #1e293b;
--text-secondary: #64748b;
--text-muted: #94a3b8;
--border: #e2e8f0;
--border-light: #f1f5f9;
--gradient-1: linear-gradient(135deg, #6366f1, #8b5cf6, #ec4899);
--gradient-2: linear-gradient(135deg, #f59e0b, #ef4444, #ec4899);
--shadow: 0 4px 24px rgba(99, 102, 241, 0.08);
--shadow-hover: 0 12px 40px rgba(99, 102, 241, 0.14);
--radius: 20px;
}
html { scroll-behavior: smooth; }
body {
font-family: 'Inter', 'PingFang SC', 'Microsoft YaHei', -apple-system, BlinkMacSystemFont, sans-serif;
background-color: var(--bg-page);
color: var(--text-primary);
min-height: 100vh;
overflow-x: hidden;
-webkit-font-smoothing: antialiased;
line-height: 1.6;
}
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: var(--bg-page); }
::-webkit-scrollbar-thumb { background: var(--primary); border-radius: 3px; }
/* ========== 装饰背景 ========== */
.bg-decoration {
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.bg-circle {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.6;
}
.bg-circle-1 {
width: 500px; height: 500px;
background: rgba(99, 102, 241, 0.08);
top: -150px; right: -100px;
animation: floatBg 25s ease-in-out infinite;
}
.bg-circle-2 {
width: 400px; height: 400px;
background: rgba(236, 72, 153, 0.05);
bottom: 10%; left: -80px;
animation: floatBg 20s ease-in-out infinite reverse;
}
.bg-circle-3 {
width: 300px; height: 300px;
background: rgba(245, 158, 11, 0.05);
top: 50%; right: 10%;
animation: floatBg 18s ease-in-out infinite;
animation-delay: -8s;
}
@keyframes floatBg {
0%, 100% { transform: translate(0, 0) scale(1); }
33% { transform: translate(30px, -40px) scale(1.08); }
66% { transform: translate(-20px, 30px) scale(0.96); }
}
/* ========== 导航栏 ========== */
.navbar {
position: fixed;
top: 0; left: 0; right: 0;
z-index: 100;
padding: 0 48px;
height: 72px;
display: flex;
align-items: center;
justify-content: space-between;
background: rgba(248, 249, 252, 0.82);
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
border-bottom: 1px solid var(--border);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.navbar.scrolled {
height: 62px;
background: rgba(248, 249, 252, 0.96);
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.06);
}
.nav-brand {
display: flex;
align-items: center;
gap: 12px;
text-decoration: none;
color: var(--text-primary);
}
.nav-brand-icon {
width: 40px;
height: 40px;
border-radius: 12px;
background: var(--gradient-1);
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.nav-brand:hover .nav-brand-icon {
transform: rotate(-8deg) scale(1.08);
box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4);
}
.nav-brand-text {
font-size: 18px;
font-weight: 700;
letter-spacing: -0.3px;
background: var(--gradient-1);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.nav-links { display: flex; align-items: center; gap: 8px; }
.nav-link {
padding: 8px 18px;
border-radius: 10px;
color: var(--text-secondary);
text-decoration: none;
font-size: 14px;
font-weight: 500;
transition: all 0.3s ease;
}
.nav-link:hover { color: var(--primary); background: rgba(99, 102, 241, 0.06); }
.nav-link.active { color: var(--primary); background: rgba(99, 102, 241, 0.1); }
.nav-link-admin {
padding: 8px 20px;
background: var(--gradient-1);
color: #fff !important;
border-radius: 10px;
font-weight: 600;
box-shadow: 0 4px 15px rgba(99, 102, 241, 0.3);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.nav-link-admin:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(99, 102, 241, 0.4);
}
/* ========== Hero ========== */
.hero {
position: relative;
z-index: 1;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 120px 24px 80px;
}
.hero-badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 20px;
background: rgba(99, 102, 241, 0.08);
border: 1px solid rgba(99, 102, 241, 0.15);
border-radius: 50px;
font-size: 13px;
color: var(--primary);
font-weight: 500;
margin-bottom: 32px;
animation: fadeInUp 0.8s ease forwards;
opacity: 0;
}
.hero-badge-dot {
width: 6px;
height: 6px;
background: var(--primary);
border-radius: 50%;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.4; transform: scale(1.6); }
}
.hero-title {
font-size: clamp(44px, 7vw, 82px);
font-weight: 800;
line-height: 1.1;
letter-spacing: -2px;
margin-bottom: 24px;
animation: fadeInUp 0.8s ease 0.15s forwards;
opacity: 0;
}
.hero-title-line { display: block; }
.hero-title-gradient {
background: var(--gradient-1);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-subtitle {
font-size: clamp(16px, 2vw, 20px);
color: var(--text-secondary);
max-width: 520px;
line-height: 1.8;
margin-bottom: 48px;
animation: fadeInUp 0.8s ease 0.3s forwards;
opacity: 0;
}
.hero-actions {
display: flex;
gap: 16px;
flex-wrap: wrap;
justify-content: center;
animation: fadeInUp 0.8s ease 0.45s forwards;
opacity: 0;
}
.btn-primary {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 14px 32px;
background: var(--gradient-1);
color: #fff;
border-radius: 14px;
font-size: 15px;
font-weight: 600;
text-decoration: none;
border: none;
cursor: pointer;
box-shadow: 0 8px 30px rgba(99, 102, 241, 0.3);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.btn-primary::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.2), transparent);
opacity: 0;
transition: opacity 0.3s;
}
.btn-primary:hover {
transform: translateY(-3px) scale(1.02);
box-shadow: 0 16px 40px rgba(99, 102, 241, 0.4);
}
.btn-primary:hover::before { opacity: 1; }
.btn-ghost {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 14px 28px;
background: var(--bg-card);
color: var(--text-primary);
border: 1.5px solid var(--border);
border-radius: 14px;
font-size: 15px;
font-weight: 500;
text-decoration: none;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}
.btn-ghost:hover {
border-color: var(--primary);
color: var(--primary);
background: rgba(99, 102, 241, 0.04);
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(99, 102, 241, 0.1);
}
.hero-scroll {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
color: var(--text-muted);
font-size: 12px;
letter-spacing: 2px;
text-transform: uppercase;
animation: fadeInUp 1s ease 1s forwards, float 3s ease-in-out infinite 1.5s;
opacity: 0;
text-decoration: none;
}
.scroll-line {
width: 1px;
height: 40px;
background: linear-gradient(to bottom, var(--primary), transparent);
animation: scrollLine 2s ease-in-out infinite;
}
@keyframes scrollLine {
0% { transform: scaleY(0); transform-origin: top; }
50% { transform: scaleY(1); transform-origin: top; }
51% { transform: scaleY(1); transform-origin: bottom; }
100% { transform: scaleY(0); transform-origin: bottom; }
}
/* ========== 文章列表 ========== */
.articles-section {
position: relative;
z-index: 1;
max-width: 1100px;
margin: 0 auto;
padding: 40px 24px 120px;
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 48px;
animation: fadeInUp 0.8s ease forwards;
opacity: 0;
}
.section-title {
font-size: 28px;
font-weight: 700;
letter-spacing: -0.5px;
display: flex;
align-items: center;
gap: 12px;
}
.section-title-icon {
width: 36px;
height: 36px;
border-radius: 10px;
background: var(--gradient-1);
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.25);
}
.section-count {
padding: 6px 16px;
background: rgba(99, 102, 241, 0.08);
border: 1px solid rgba(99, 102, 241, 0.12);
border-radius: 50px;
font-size: 13px;
color: var(--primary);
font-weight: 500;
}
.articles-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 24px;
}
.article-card {
position: relative;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 32px;
text-decoration: none;
color: inherit;
display: flex;
flex-direction: column;
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
overflow: hidden;
opacity: 0;
transform: translateY(30px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.02);
}
.article-card.visible {
opacity: 1;
transform: translateY(0);
}
.article-card:hover {
transform: translateY(-8px);
border-color: rgba(99, 102, 241, 0.2);
box-shadow: var(--shadow-hover);
background: var(--bg-card-hover);
}
.card-top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.card-tag {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 5px 12px;
background: rgba(99, 102, 241, 0.08);
border-radius: 8px;
font-size: 12px;
color: var(--primary);
font-weight: 500;
}
.card-date { font-size: 12px; color: var(--text-muted); }
.card-title {
font-size: 18px;
font-weight: 700;
line-height: 1.45;
margin-bottom: 12px;
color: var(--text-primary);
transition: color 0.3s;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.article-card:hover .card-title { color: var(--primary); }
.card-excerpt {
font-size: 14px;
color: var(--text-secondary);
line-height: 1.75;
margin-bottom: 24px;
flex-grow: 1;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.card-footer {
display: flex;
align-items: center;
justify-content: space-between;
padding-top: 20px;
border-top: 1px solid var(--border-light);
}
.card-author { display: flex; align-items: center; gap: 10px; }
.card-author-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--gradient-2);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 700;
color: #fff;
}
.card-author-name { font-size: 13px; font-weight: 500; color: var(--text-secondary); }
.card-read-more {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--primary);
font-weight: 500;
opacity: 0;
transform: translateX(-10px);
transition: all 0.3s ease;
}
.article-card:hover .card-read-more {
opacity: 1;
transform: translateX(0);
}
.empty-state {
grid-column: 1 / -1;
text-align: center;
padding: 80px 20px;
animation: fadeIn 0.6s ease;
}
.empty-icon { font-size: 64px; margin-bottom: 24px; opacity: 0.25; }
.empty-state h3 { font-size: 20px; color: var(--text-secondary); margin-bottom: 8px; }
.empty-state p { color: var(--text-muted); font-size: 14px; }
/* ========== 底部 ========== */
.footer {
position: relative;
z-index: 1;
text-align: center;
padding: 40px 24px 60px;
border-top: 1px solid var(--border);
}
.footer-text { font-size: 14px; color: var(--text-muted); }
.footer-text span { color: var(--primary); font-weight: 600; }
/* ========== 动画 ========== */
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes float {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-10px); }
}
/* ========== 响应式 ========== */
@media (max-width: 768px) {
.navbar { padding: 0 20px; }
.nav-links { gap: 4px; }
.nav-link { padding: 8px 12px; font-size: 13px; }
.nav-link-admin { padding: 8px 14px; }
.articles-grid { grid-template-columns: 1fr; }
.hero { padding: 100px 20px 80px; }
.hero-actions { flex-direction: column; align-items: center; }
.section-header { flex-direction: column; align-items: flex-start; gap: 16px; }
}
</style>
</head>
<body>
<!-- 装饰背景 -->
<div class="bg-decoration">
<div class="bg-circle bg-circle-1"></div>
<div class="bg-circle bg-circle-2"></div>
<div class="bg-circle bg-circle-3"></div>
</div>
<!-- 导航栏 -->
<nav class="navbar" id="navbar">
<a href="index.php" class="nav-brand">
<div class="nav-brand-icon">&#10022;</div>
<span class="nav-brand-text">许老师的小站</span>
</a>
<div class="nav-links">
<a href="index.php" class="nav-link active">首页</a>
<a href="main.php" class="nav-link nav-link-admin" target="_blank">后台管理</a>
</div>
</nav>
<!-- Hero -->
<section class="hero">
<div class="hero-badge">
<span class="hero-badge-dot"></span>
<span>笔记与随笔</span>
</div>
<h1 class="hero-title">
<span class="hero-title-line">记录思考,</span>
<span class="hero-title-line hero-title-gradient">沉淀成长</span>
</h1>
<p class="hero-subtitle">
在这里,每一次敲击键盘都是一次思维的碰撞,每一篇文章都是对知识的重新梳理。
</p>
<div class="hero-actions">
<a href="#articles" class="btn-primary">
<span>探索文章</span>
<span>&#8595;</span>
</a>
<a href="main.php" class="btn-ghost" target="_blank">后台管理</a>
</div>
<a href="#articles" class="hero-scroll">
<span>向下滚动</span>
<div class="scroll-line"></div>
</a>
</section>
<!-- 文章列表 -->
<section class="articles-section" id="articles">
<div class="section-header">
<h2 class="section-title">
<div class="section-title-icon">&#128221;</div>
全部文章
</h2>
<?php
include("db.php");
$sql = "SELECT COUNT(*) as total FROM articles";
$countResult = mysqli_query($conn, $sql);
$countRow = mysqli_fetch_assoc($countResult);
?>
<span class="section-count"><?php echo $countRow['total']; ?> 篇</span>
</div>
<div class="articles-grid">
<?php
$sql = "SELECT * FROM articles ORDER BY id DESC";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) === 0) {
echo '<div class="empty-state">
<div class="empty-icon">&#128579;</div>
<h3>暂无文章</h3>
<p>点击右上角「后台管理」添加你的第一篇文章吧</p>
</div>';
}
while ($row = mysqli_fetch_assoc($result)) {
$excerpt = mb_substr(strip_tags($row["content"]), 0, 80, 'utf-8');
if (mb_strlen(strip_tags($row["content"]), 'utf-8') > 80) $excerpt .= '…';
$authorInitial = mb_substr($row["author"], 0, 1, 'utf-8');
?>
<a href="article.php?id=<?php echo $row["id"]; ?>" class="article-card">
<div class="card-top">
<span class="card-tag">&#128196; 笔记</span>
<span class="card-date"><?php echo date('m/d', strtotime($row["time"])); ?></span>
</div>
<h3 class="card-title"><?php echo $row["title"]; ?></h3>
<p class="card-excerpt"><?php echo $excerpt; ?></p>
<div class="card-footer">
<div class="card-author">
<div class="card-author-avatar"><?php echo $authorInitial; ?></div>
<span class="card-author-name"><?php echo $row["author"]; ?></span>
</div>
<span class="card-read-more">阅读全文 &#8594;</span>
</div>
</a>
<?php } ?>
</div>
</section>
<!-- 底部 -->
<footer class="footer">
<p class="footer-text">
&copy; <?php echo date('Y'); ?> <span>许老师的小站</span> &middot; 用心记录每一天
</p>
</footer>
<script>
const navbar = document.getElementById('navbar');
window.addEventListener('scroll', () => {
navbar.classList.toggle('scrolled', window.scrollY > 50);
}, { passive: true });
const cards = document.querySelectorAll('.article-card');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => entry.target.classList.add('visible'), index * 80);
observer.unobserve(entry.target);
}
});
}, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
cards.forEach(card => observer.observe(card));
cards.forEach(card => {
card.addEventListener('click', function(e) {
const ripple = document.createElement('div');
ripple.style.cssText = 'position:absolute;border-radius:50%;background:rgba(99,102,241,0.1);transform:scale(0);animation:rippleOut 0.6s ease-out forwards;pointer-events:none;';
const rect = this.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = (e.clientX - rect.left - size / 2) + 'px';
ripple.style.top = (e.clientY - rect.top - size / 2) + 'px';
this.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
});
});
const s = document.createElement('style');
s.textContent = '@keyframes rippleOut { to { transform:scale(4); opacity:0; } }';
document.head.appendChild(s);
</script>
</body>
</html>

View File

@@ -0,0 +1,415 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>欢迎登录</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
overflow: hidden;
}
/* 装饰背景 */
.bg-decoration {
position: fixed;
border-radius: 50%;
filter: blur(80px);
opacity: 0.5;
z-index: 0;
animation: float 8s ease-in-out infinite;
}
.bg-decoration:nth-child(1) {
width: 400px;
height: 400px;
background: rgba(102, 126, 234, 0.6);
top: -100px;
left: -100px;
animation-delay: 0s;
}
.bg-decoration:nth-child(2) {
width: 300px;
height: 300px;
background: rgba(240, 147, 251, 0.5);
bottom: -50px;
right: -50px;
animation-delay: -2s;
}
.bg-decoration:nth-child(3) {
width: 200px;
height: 200px;
background: rgba(255, 255, 255, 0.3);
top: 50%;
right: 10%;
animation-delay: -4s;
}
@keyframes float {
0%,
100% {
transform: translate(0, 0) scale(1);
}
25% {
transform: translate(20px, -20px) scale(1.05);
}
50% {
transform: translate(0, -30px) scale(1);
}
75% {
transform: translate(-20px, -10px) scale(1.03);
}
}
/* 登录卡片 */
.login-card {
position: relative;
z-index: 1;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-radius: 24px;
padding: 48px 40px;
width: 420px;
max-width: 90vw;
box-shadow:
0 25px 50px -12px rgba(0, 0, 0, 0.25),
0 0 0 1px rgba(255, 255, 255, 0.5) inset;
animation: slideUp 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(40px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
/* 标题 */
.login-title {
text-align: center;
margin-bottom: 40px;
}
.login-title h1 {
font-size: 28px;
font-weight: 600;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 8px;
}
.login-title p {
font-size: 14px;
color: #6b7280;
}
/* 输入框容器 */
.input-group {
position: relative;
margin-bottom: 24px;
}
.input-group input {
width: 100%;
padding: 16px 20px;
font-size: 16px;
border: 2px solid #e5e7eb;
border-radius: 12px;
outline: none;
background: #f9fafb;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.input-group input::placeholder {
color: #9ca3af;
transition: all 0.3s ease;
}
.input-group input:focus {
border-color: #667eea;
background: #ffffff;
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.15);
}
.input-group input:focus::placeholder {
opacity: 0.5;
transform: translateX(4px);
}
/* 输入框图标 */
.input-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
color: #9ca3af;
transition: all 0.3s ease;
pointer-events: none;
}
.input-group input:focus~.input-icon {
color: #667eea;
}
.input-group input {
padding-left: 48px;
}
/* 记住我 & 忘记密码 */
.form-options {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 28px;
}
.remember-me {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
}
.remember-me input[type="checkbox"] {
display: none;
}
.checkmark {
width: 18px;
height: 18px;
border: 2px solid #d1d5db;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.remember-me:hover .checkmark {
border-color: #667eea;
}
.remember-me input:checked+.checkmark {
background: #667eea;
border-color: #667eea;
}
.checkmark::after {
content: '✓';
font-size: 12px;
color: white;
opacity: 0;
transform: scale(0);
transition: all 0.2s ease;
}
.remember-me input:checked+.checkmark::after {
opacity: 1;
transform: scale(1);
}
.remember-me span {
font-size: 14px;
color: #6b7280;
}
.forgot-password {
font-size: 14px;
color: #667eea;
text-decoration: none;
transition: all 0.2s ease;
}
.forgot-password:hover {
color: #764ba2;
}
/* 登录按钮 */
.login-btn {
width: 100%;
padding: 16px;
font-size: 16px;
font-weight: 600;
color: white;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 12px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.login-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.5s ease;
}
.login-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -5px rgba(102, 126, 234, 0.5);
}
.login-btn:hover::before {
left: 100%;
}
.login-btn:active {
transform: translateY(0);
box-shadow: 0 5px 15px -3px rgba(102, 126, 234, 0.4);
}
/* 注册链接 */
.signup-link {
text-align: center;
margin-top: 28px;
font-size: 14px;
color: #6b7280;
}
.signup-link a {
color: #667eea;
text-decoration: none;
font-weight: 500;
transition: all 0.2s ease;
}
.signup-link a:hover {
color: #764ba2;
}
/* 分隔线 */
.divider {
display: flex;
align-items: center;
margin: 28px 0;
gap: 16px;
}
.divider::before,
.divider::after {
content: '';
flex: 1;
height: 1px;
background: linear-gradient(90deg, transparent, #e5e7eb, transparent);
}
.divider span {
font-size: 12px;
color: #9ca3af;
text-transform: uppercase;
letter-spacing: 1px;
}
/* 社交登录 */
.social-login {
display: flex;
gap: 12px;
}
.social-btn {
flex: 1;
padding: 12px;
border: 2px solid #e5e7eb;
border-radius: 10px;
background: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
font-size: 14px;
color: #6b7280;
transition: all 0.3s ease;
}
.social-btn:hover {
border-color: #667eea;
background: #f9fafb;
transform: translateY(-2px);
}
.social-btn svg {
width: 20px;
height: 20px;
}
</style>
</head>
<body>
<!-- 装饰背景 -->
<div class="bg-decoration"></div>
<div class="bg-decoration"></div>
<div class="bg-decoration"></div>
<div class="login-card">
<div class="login-title">
<h1>欢迎登录</h1>
<p>请输入您的账号信息</p>
</div>
<form action="users.php" method="POST">
<!-- GET提交方式所有的信息都在网址中 -->
<!-- POST提交方式所有的信息都在请求体中 -->
<div class="input-group">
<input type="text" placeholder="用户名" name="username" required>
<span class="input-icon">👤</span>
</div>
<div class="input-group">
<input type="text" placeholder="密码" name="password" required>
<span class="input-icon">🔒</span>
</div>
<div class="form-options">
<label class="remember-me">
<input type="checkbox" name="remember">
<span class="checkmark"></span>
<span>记住我</span>
</label>
<a href="#" class="forgot-password">忘记密码?</a>
</div>
<input type="submit" class="login-btn" name="login" value="登 录">
</form>
<div class="signup-link">
还没有账号?<a href="register.php">立即注册</a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,87 @@
<?php
$pageTitle = '网站后台管理 - 网站信息';
$page = 'main';
include("header.php");
?>
<main class="main-content">
<div class="welcome-section">
<h2>仪表盘</h2>
<p>实时监控网站运行状态</p>
</div>
<?php
// 获取服务器的内存占用
//$memoryUsage = exec('powershell -c "$os=Get-CimInstance Win32_OperatingSystem;$pct=[math]::Round(($os.TotalVisibleMemorySize-$os.FreePhysicalMemory)*100/$os.TotalVisibleMemorySize,1);echo $pct"');
// 目前用随机数代替
$memoryUsage = mt_rand(30, 60);
// 获取服务器的CPU占用
//$cpuUsage = exec('powershell -c "(Get-CimInstance Win32_Processor).LoadPercentage"');
$cpuUsage = mt_rand(30, 60);
?>
<div class="stats-grid">
<div class="stat-card visitors">
<div class="card-icon">👥</div>
<div class="stat-label">今日访客</div>
<div class="stat-value">1000</div>
</div>
<div class="stat-card memory">
<div class="card-icon">💾</div>
<div class="stat-label">服务内存占用</div>
<div class="stat-value"><?php echo $memoryUsage; ?><span class="stat-unit">%</span></div>
</div>
<div class="stat-card cpu">
<div class="card-icon">⚙️</div>
<div class="stat-label">服务器 CPU 占用</div>
<div class="stat-value"><?php echo $cpuUsage; ?><span class="stat-unit">%</span></div>
</div>
<div class="stat-card site">
<div class="card-icon">🌐</div>
<div class="stat-label">站点名称</div>
<div class="stat-value" style="font-size: 20px;">许老师的小站</div>
</div>
</div>
<div class="content-card">
<h3>快速信息</h3>
<div class="info-list">
<div class="info-item">
<div class="info-icon">🏠</div>
<div class="info-text">
<h4>站点状态</h4>
<p>运行正常</p>
</div>
</div>
<div class="info-item">
<div class="info-icon">🕐</div>
<div class="info-text">
<h4>系统时间</h4>
<p id="current-time">加载中...</p>
</div>
</div>
<div class="info-item">
<div class="info-icon">📅</div>
<div class="info-text">
<h4>系统日期</h4>
<p id="current-date">加载中...</p>
</div>
</div>
</div>
</div>
</main>
<script>
function updateTime() {
const now = new Date();
const timeStr = now.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
const dateStr = now.toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' });
document.getElementById('current-time').textContent = timeStr;
document.getElementById('current-date').textContent = dateStr;
}
updateTime();
setInterval(updateTime, 1000);
</script>
</body>
</html>

View File

@@ -0,0 +1,416 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>欢迎注册</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
overflow: hidden;
}
/* 装饰背景 */
.bg-decoration {
position: fixed;
border-radius: 50%;
filter: blur(80px);
opacity: 0.5;
z-index: 0;
animation: float 8s ease-in-out infinite;
}
.bg-decoration:nth-child(1) {
width: 400px;
height: 400px;
background: rgba(102, 126, 234, 0.6);
top: -100px;
left: -100px;
animation-delay: 0s;
}
.bg-decoration:nth-child(2) {
width: 300px;
height: 300px;
background: rgba(240, 147, 251, 0.5);
bottom: -50px;
right: -50px;
animation-delay: -2s;
}
.bg-decoration:nth-child(3) {
width: 200px;
height: 200px;
background: rgba(255, 255, 255, 0.3);
top: 50%;
right: 10%;
animation-delay: -4s;
}
@keyframes float {
0%,
100% {
transform: translate(0, 0) scale(1);
}
25% {
transform: translate(20px, -20px) scale(1.05);
}
50% {
transform: translate(0, -30px) scale(1);
}
75% {
transform: translate(-20px, -10px) scale(1.03);
}
}
/* 登录卡片 */
.login-card {
position: relative;
z-index: 1;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(20px);
border-radius: 24px;
padding: 48px 40px;
width: 420px;
max-width: 90vw;
box-shadow:
0 25px 50px -12px rgba(0, 0, 0, 0.25),
0 0 0 1px rgba(255, 255, 255, 0.5) inset;
animation: slideUp 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(40px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
/* 标题 */
.login-title {
text-align: center;
margin-bottom: 40px;
}
.login-title h1 {
font-size: 28px;
font-weight: 600;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 8px;
}
.login-title p {
font-size: 14px;
color: #6b7280;
}
/* 输入框容器 */
.input-group {
position: relative;
margin-bottom: 24px;
}
.input-group input {
width: 100%;
padding: 16px 20px;
font-size: 16px;
border: 2px solid #e5e7eb;
border-radius: 12px;
outline: none;
background: #f9fafb;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.input-group input::placeholder {
color: #9ca3af;
transition: all 0.3s ease;
}
.input-group input:focus {
border-color: #667eea;
background: #ffffff;
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.15);
}
.input-group input:focus::placeholder {
opacity: 0.5;
transform: translateX(4px);
}
/* 输入框图标 */
.input-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
color: #9ca3af;
transition: all 0.3s ease;
pointer-events: none;
}
.input-group input:focus~.input-icon {
color: #667eea;
}
.input-group input {
padding-left: 48px;
}
/* 记住我 & 忘记密码 */
.form-options {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 28px;
}
.remember-me {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
}
.remember-me input[type="checkbox"] {
display: none;
}
.checkmark {
width: 18px;
height: 18px;
border: 2px solid #d1d5db;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
.remember-me:hover .checkmark {
border-color: #667eea;
}
.remember-me input:checked+.checkmark {
background: #667eea;
border-color: #667eea;
}
.checkmark::after {
content: '✓';
font-size: 12px;
color: white;
opacity: 0;
transform: scale(0);
transition: all 0.2s ease;
}
.remember-me input:checked+.checkmark::after {
opacity: 1;
transform: scale(1);
}
.remember-me span {
font-size: 14px;
color: #6b7280;
}
.forgot-password {
font-size: 14px;
color: #667eea;
text-decoration: none;
transition: all 0.2s ease;
}
.forgot-password:hover {
color: #764ba2;
}
/* 登录按钮 */
.login-btn {
width: 100%;
padding: 16px;
font-size: 16px;
font-weight: 600;
color: white;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
border-radius: 12px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.login-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.5s ease;
}
.login-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px -5px rgba(102, 126, 234, 0.5);
}
.login-btn:hover::before {
left: 100%;
}
.login-btn:active {
transform: translateY(0);
box-shadow: 0 5px 15px -3px rgba(102, 126, 234, 0.4);
}
/* 注册链接 */
.signup-link {
text-align: center;
margin-top: 28px;
font-size: 14px;
color: #6b7280;
}
.signup-link a {
color: #667eea;
text-decoration: none;
font-weight: 500;
transition: all 0.2s ease;
}
.signup-link a:hover {
color: #764ba2;
}
/* 分隔线 */
.divider {
display: flex;
align-items: center;
margin: 28px 0;
gap: 16px;
}
.divider::before,
.divider::after {
content: '';
flex: 1;
height: 1px;
background: linear-gradient(90deg, transparent, #e5e7eb, transparent);
}
.divider span {
font-size: 12px;
color: #9ca3af;
text-transform: uppercase;
letter-spacing: 1px;
}
/* 社交登录 */
.social-login {
display: flex;
gap: 12px;
}
.social-btn {
flex: 1;
padding: 12px;
border: 2px solid #e5e7eb;
border-radius: 10px;
background: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
font-size: 14px;
color: #6b7280;
transition: all 0.3s ease;
}
.social-btn:hover {
border-color: #667eea;
background: #f9fafb;
transform: translateY(-2px);
}
.social-btn svg {
width: 20px;
height: 20px;
}
</style>
</head>
<body>
<!-- 装饰背景 -->
<div class="bg-decoration"></div>
<div class="bg-decoration"></div>
<div class="bg-decoration"></div>
<div class="login-card">
<div class="login-title">
<h1>欢迎注册</h1>
<p>请创建您的账号信息</p>
</div>
<form action="users.php" method="POST">
<!-- GET提交方式所有的信息都在网址中 -->
<!-- POST提交方式所有的信息都在请求体中 -->
<div class="input-group">
<input type="text" placeholder="用户名" name="username" required>
<span class="input-icon">👤</span>
</div>
<div class="input-group">
<input type="text" placeholder="密码" name="password" required>
<span class="input-icon">🔒</span>
</div>
<div class="input-group">
<input type="text" placeholder="确认密码" name="password2" required>
<span class="input-icon">🔒</span>
</div>
<div class="input-group">
<input type="text" placeholder="邮箱" name="email" required>
<span class="input-icon">📧</span>
</div>
<input type="submit" class="login-btn" value="注 册" name="register">
</form>
<div class="signup-link">
已有账号?<a href="login.php">立即登录</a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<?php
// 字符集设置为utf-8
header("Content-Type: text/html; charset=UTF-8");
// 连接mysql数据库
$host = "127.0.0.1";
$dbname = "root";
$dbpassword = "usbw";
$database = "blog";
$port = 3307;
$conn = mysqli_connect($host, $dbname, $dbpassword, $database, $port);
if (!$conn) {
echo "连接失败";
exit;
}
// 获取users表中的所有数据
$sql = "select * from users";
$result = mysqli_query($conn, $sql);
if (!$result) {
echo "查询失败";
exit;
}
// 将查询的数据一行行输出
// mysqli_fetch_assoc函数是将查询的数据以关联数组的形式返回数组的key是字段名value是字段值
while ($row = mysqli_fetch_assoc($result)) {
echo "<p>" . $row["username"] . ":" . $row["email"] . ":" . $row["password"] . "</p>";
}

View File

@@ -0,0 +1,54 @@
<?php
$pageTitle = '网站后台管理 - 用户添加';
$page = 'users';
include("header.php");
?>
<?php
// 根据传递的id获取表中的各个信息
// 连接mysql数据库
include("db.php");
$userid = $_REQUEST["id"];
$sql = "select * from users where id='$userid'";
$result = mysqli_query($conn, $sql);
$user = mysqli_fetch_assoc($result);
?>
<main class="main-content">
<div class="page-header">
<h2>添加用户</h2>
<p>添加用户信息</p>
</div>
<div class="form-card form-card-sm">
<form action="users.php" method="post">
<div class="form-group">
<label for="username">用户名</label>
<input type="text" id="username" name="username" placeholder="请输入用户名" required>
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" name="password" placeholder="请输入新密码" required>
</div>
<div class="form-group">
<label for="password2">确认密码</label>
<input type="password" id="password2" name="password2" placeholder="请再次输入新密码" required>
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" id="email" name="email" placeholder="请输入邮箱地址" required>
</div>
<div class="btn-group">
<input type="submit" class="btn btn-primary" value="添加" name="add">
<a href="users_list.php" class="btn btn-secondary">取消</a>
</div>
</form>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,136 @@
<?php
$pageTitle = '网站后台管理 - 头像修改';
$page = 'users';
include("header.php");
?>
<?php
include("db.php");
if (count($_FILES) > 0) {
// php传图片会默认放在临时目录下在程序执行结束后就会自动删除
// php上传图片本质上就是从临时目录中将文件及时移动到指定目录下
// 先获取图片的格式
$ext = pathinfo($_FILES["avatar"]["name"], PATHINFO_EXTENSION);
$img_path = "images/avatar/" . date("YmdHis") . mt_rand(10000, 99999) . "." . $ext;
move_uploaded_file($_FILES["avatar"]["tmp_name"], $img_path);
// 写入数据库中
$id = $_GET["id"];
$sql = "UPDATE users SET avatar = '$img_path' WHERE id = $id";
if (mysqli_query($conn, $sql) === TRUE) {
echo "<script>alert('头像修改成功');location.href='users_list.php'</script>";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
}
// 获取当前的头像
$sql = "select * from users where id = '" . $_GET["id"] . "'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_assoc($result);
$avatar = $row["avatar"];
?>
<main class="main-content">
<div class="page-header page-header-bar">
<div>
<h2>头像修改</h2>
<p>更新用户头像</p>
</div>
</div>
<div class="form-card">
<div class="avatar-preview">
<div class="avatar-current">
<p class="avatar-label">当前头像</p>
<div class="avatar-img-wrap">
<?php if ($avatar): ?>
<img src="<?php echo $avatar; ?>" alt="当前头像">
<?php else: ?>
<div class="avatar-placeholder">&#128100;</div>
<?php endif; ?>
</div>
</div>
</div>
<form action="" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="avatar">上传新头像</label>
<div class="file-upload-wrap">
<input type="file" name="avatar" id="avatar" accept="image/*" required>
</div>
<p class="form-hint">支持 JPG、PNG、GIF 格式,文件大小不超过 2MB</p>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary">
<span>&#128190;</span>
<span>上传头像</span>
</button>
<a href="users_list.php" class="btn btn-secondary">取消</a>
</div>
</form>
</div>
</main>
<style>
.avatar-preview {
display: flex;
justify-content: center;
margin-bottom: 32px;
}
.avatar-current {
text-align: center;
}
.avatar-label {
font-size: 14px;
color: #6b7280;
margin-bottom: 16px;
letter-spacing: 0.5px;
}
.avatar-img-wrap {
width: 120px;
height: 120px;
border-radius: 50%;
overflow: hidden;
border: 3px solid #e5e7eb;
background: #f9fafb;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
transition: border-color 0.2s ease;
}
.avatar-img-wrap:hover {
border-color: #3b82f6;
}
.avatar-img-wrap img {
width: 100%;
height: 100%;
object-fit: cover;
}
.avatar-placeholder {
font-size: 48px;
color: #9ca3af;
}
.file-upload-wrap input[type="file"] {
padding: 10px 16px;
background: #f9fafb;
border: 2px dashed #d1d5db;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.file-upload-wrap input[type="file"]:hover {
border-color: #3b82f6;
background: #eff6ff;
}
</style>
</body>
</html>

View File

@@ -0,0 +1,56 @@
<?php
$pageTitle = '网站后台管理 - 用户编辑';
$page = 'users';
include("header.php");
?>
<?php
// 根据传递的id获取表中的各个信息
// 连接mysql数据库
include("db.php");
$userid = $_REQUEST["id"];
$sql = "select * from users where id='$userid'";
$result = mysqli_query($conn, $sql);
$user = mysqli_fetch_assoc($result);
?>
<main class="main-content">
<div class="page-header">
<h2>编辑用户</h2>
<p>修改用户信息</p>
</div>
<div class="form-card form-card-sm">
<form action="users.php" method="post">
<input type="hidden" value="<?php echo $user["id"]; ?>" name="id">
<div class="form-group">
<label for="username">用户名</label>
<input type="text" id="username" name="username" placeholder="请输入用户名" value="<?php echo $user["username"]; ?>">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" name="password" placeholder="请输入新密码">
<p class="form-hint">密码留空则不修改</p>
</div>
<div class="form-group">
<label for="password2">确认密码</label>
<input type="password" id="password2" name="password2" placeholder="请再次输入新密码">
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" id="email" name="email" placeholder="请输入邮箱地址" value="<?php echo $user["email"]; ?>">
</div>
<div class="btn-group">
<input type="submit" class="btn btn-primary" value="保存" name="change">
<a href="users_list.php" class="btn btn-secondary">取消</a>
</div>
</form>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,116 @@
<?php
// 处理用户登录、注册、修改、退出、删除相关的代码
// 设置页面的字符编码为UTF-8
header("Content-Type: text/html; charset=UTF-8");
// 连接mysql数据库
// include函数相当于将db.php文件中的代码复制到这里就不用在每个页面中都写一遍了
include("db.php");
session_start();
// 先判断$_REQUEST中是否存在'login'或'register'参数,如果存在,则执行对应的操作,否则返回错误信息
// isset 判断变量是否存在
if (isset($_REQUEST["login"])) {
// 从前端接受用户名和密码,并且去数据库中验证
$username = $_REQUEST["username"];
$password = $_REQUEST["password"];
// 写sql语句
$sql = "select * from users where username='$username' and password='$password'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
$_SESSION["username"] = $username;
echo "<script>alert('登录成功');location.href='main.php'</script>";
} else {
echo "<script>alert('登录失败');location.href='login.php'</script>";
}
} else if (isset($_REQUEST["register"]) or isset( $_REQUEST["add"])) {
// 从前端获取用户名,以及两次密码输入,以及邮箱
$username = $_REQUEST["username"];
$password = $_REQUEST["password"];
$password2 = $_REQUEST["password2"];
$email = $_REQUEST["email"];
// 判断两次密码是否一致
if ($password != $password2) {
echo "两次密码不一致";
exit;
}
// 判断用户名或邮箱是否已存在
$sql = "select * from users where username='$username' or email='$email'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
echo "用户名或邮箱已存在";
exit;
}
// 写sql语句插入一条新的用户记录
$sql = "insert into users(username, password, email) values('$username', '$password', '$email')";
$result = mysqli_query($conn, $sql);
// 插入成功后,返回注册成功信息
if ($result) {
if(isset($_REQUEST["add"])) {
echo "<script>alert('添加成功');location.href='users_list.php'</script>";
} else {
echo "<script>alert('注册成功');location.href='login.php'</script>";
}
} else {
if(isset($_REQUEST["add"])) {
echo "<script>alert('添加失败');location.href='users_list.php'</script>";
} else {
echo "<script>alert('注册失败');location.href='login.php'</script>";
}
}
} else if (isset($_REQUEST["change"])) {
// 修改用户信息的操作
$userid = $_REQUEST["id"];
$username = $_REQUEST["username"];
$email = $_REQUEST["email"];
// 判断是否需要修改密码,判断密码的长度
if (strlen($_REQUEST["password"]) > 0) {
$password = $_REQUEST["password"];
$password2 = $_REQUEST["password2"];
if ($password != $password2) {
echo "<script>alert('两次密码不一致');location.href='users_list.php'</script>";
exit;
}
// 更新用户名,密码,邮箱
// 存在逻辑漏洞,没有判断用户名是否存在,可以修改别人的用户名
$sql = "update users set username='$username', password='$password', email='$email' where id='$userid'";
$result = mysqli_query($conn, $sql);
if ($result) {
echo "<script>alert('修改成功');location.href='users_list.php'</script>";
} else {
echo "<script>alert('修改失败');location.href='users_list.php'</script>";
}
} else {
// 更新用户名和邮箱
$sql = "update users set username='$username', email='$email' where id='$userid'";
$result = mysqli_query($conn, $sql);
if ($result) {
echo "<script>alert('修改成功');location.href='users_list.php'</script>";
} else {
echo "<script>alert('修改失败');location.href='users_list.php'</script>";
}
}
} else if (isset($_REQUEST["del"])) {
// 删除用户
$userid = $_REQUEST["id"];
$sql = "delete from users where id='$userid'";
$result = mysqli_query($conn, $sql);
if ($result) {
echo "<script>alert('删除成功');location.href='users_list.php'</script>";
} else {
echo "<script>alert('删除失败');location.href='users_list.php'</script>";
}
} else {
echo "错误操作";
}
?>

View File

@@ -0,0 +1,181 @@
<?php
$pageTitle = '网站后台管理 - 用户列表';
$page = 'users';
include("header.php");
?>
<main class="main-content">
<div class="page-header page-header-bar">
<div>
<h2>用户管理</h2>
<p>管理系统用户账号</p>
</div>
<a href="user_add.php" class="btn-add">
<span>+</span>
<span>添加用户</span>
</a>
</div>
<div class="table-container">
<table class="users-table">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php
// 连接mysql数据库
include("db.php");
// 获取users表中的所有数据
$sql = "select * from users";
$result = mysqli_query($conn, $sql);
if (!$result) {
echo "查询失败";
exit;
}
// 将查询的数据一行行输出
// mysqli_fetch_assoc函数是将查询的数据以关联数组的形式返回数组的key是字段名value是字段值
while ($row = mysqli_fetch_assoc($result)) {
?>
<tr>
<td><?php echo $row["id"];?></td>
<td>
<span class="username-tooltip">
<?php echo $row["username"];?>
<span class="tooltip-content">
<?php if ($row["avatar"]): ?>
<img src="<?php echo $row["avatar"];?>" alt="头像">
<?php else: ?>
<div class="tooltip-avatar-placeholder">&#128100;</div>
<?php endif; ?>
</span>
</span>
</td>
<td><span class="password-masked"><?php echo $row["password"];?></span></td>
<td><?php echo $row["email"];?></td>
<td>
<div class="action-btns">
<a href="user_edit.php?id=<?php echo $row["id"];?>" class="btn btn-edit">✏️ 编辑</a>
<a href="users.php?del&id=<?php echo $row["id"];?>" class="btn btn-delete"
onclick="return confirm('确定要删除该用户吗?')">🗑️ 删除</a>
<a href="user_avatar.php?id=<?php echo $row["id"];?>" class="btn btn-edit">&#128100; 修改头像</a>
</div>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</main>
<style>
.username-tooltip {
position: relative;
cursor: pointer;
color: #3b82f6;
font-weight: 500;
display: inline-block;
}
.users-table td:nth-child(2) {
position: relative;
overflow: visible;
}
.table-container {
overflow: visible !important;
}
.users-table {
overflow: visible !important;
}
.username-tooltip:hover {
text-decoration: underline;
}
.tooltip-content {
display: none;
position: absolute;
left: 50%;
bottom: calc(100% + 10px);
transform: translateX(-50%);
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 12px;
padding: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
z-index: 9999;
white-space: nowrap;
overflow: visible;
}
.tooltip-content::after {
content: '';
position: absolute;
left: 50%;
bottom: -6px;
transform: translateX(-50%);
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid #ffffff;
}
.tooltip-content::before {
content: '';
position: absolute;
left: 50%;
bottom: -7px;
transform: translateX(-50%);
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid #e5e7eb;
}
.username-tooltip:hover .tooltip-content {
display: block;
animation: tooltipFadeIn 0.2s ease;
}
.tooltip-content img {
width: 80px;
height: 80px;
border-radius: 50%;
object-fit: cover;
display: block;
}
.tooltip-avatar-placeholder {
width: 80px;
height: 80px;
border-radius: 50%;
background: #f3f4f6;
display: flex;
align-items: center;
justify-content: center;
font-size: 36px;
color: #9ca3af;
}
@keyframes tooltipFadeIn {
from {
opacity: 0;
transform: translateX(-50%) translateY(4px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
}
</style>
</body>
</html>