上传文件至 /

This commit is contained in:
2025-11-30 13:06:28 +00:00
parent c56dca6129
commit 9600be072a
5 changed files with 620 additions and 0 deletions

102
login.php Normal file
View File

@@ -0,0 +1,102 @@
<?php
require_once 'config.php';
if (isset($_SESSION['user_id'])) {
header('Location: dashboard.php');
exit;
}
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email']);
$password = $_POST['password'];
if (empty($email) || empty($password)) {
$error = t('fill_all_fields');
} else {
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
if (!$user['is_verified']) {
$error = t('verify_email_first');
} else {
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['email'] = $user['email'];
header('Location: dashboard.php');
exit;
}
} else {
$error = t('invalid_credentials');
}
}
}
?>
<!DOCTYPE html>
<html lang="<?php echo $lang; ?>" data-theme="<?php echo $currentUserSettings['dark_mode'] ? 'dark' : 'light'; ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo t('login'); ?> - <?php echo SITE_NAME; ?></title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<?php include 'components/navbar.php'; ?>
<div class="container">
<div class="auth-container">
<div class="auth-card card">
<h2><i class="fas fa-sign-in-alt"></i> <?php echo t('user_login'); ?></h2>
<?php if($error): ?>
<div class="alert alert-error">
<i class="fas fa-exclamation-triangle"></i> <?php echo $error; ?>
</div>
<?php endif; ?>
<form method="POST" action="">
<div class="form-group">
<label for="email">
<i class="fas fa-envelope"></i> <?php echo t('email'); ?>
</label>
<input type="email" id="email" name="email" required
value="<?php echo isset($_POST['email']) ? htmlspecialchars($_POST['email']) : ''; ?>"
placeholder="<?php echo t('enter_email'); ?>">
</div>
<div class="form-group">
<label for="password">
<i class="fas fa-lock"></i> <?php echo t('password'); ?>
</label>
<input type="password" id="password" name="password" required
placeholder="<?php echo t('enter_password'); ?>">
</div>
<button type="submit" class="btn btn-primary btn-full">
<i class="fas fa-sign-in-alt"></i> <?php echo t('login'); ?>
</button>
</form>
<div class="auth-links">
<p>
<a href="forgot-password.php">
<i class="fas fa-key"></i> <?php echo t('forgot_password'); ?>
</a>
</p>
<p>
<?php echo t('no_account'); ?>
<a href="register.php">
<i class="fas fa-user-plus"></i> <?php echo t('register_now'); ?>
</a>
</p>
</div>
</div>
</div>
</div>
</body>
</html>

18
logout.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
require_once 'config.php';
$_SESSION = array();
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
session_destroy();
header('Location: index.php');
exit;
?>

194
notifications.php Normal file
View File

@@ -0,0 +1,194 @@
<?php
require_once 'config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
// 标记通知为已读
if (isset($_GET['mark_read'])) {
$notification_id = intval($_GET['mark_read']);
$stmt = $pdo->prepare("UPDATE notifications SET is_read = TRUE WHERE id = ? AND user_id = ?");
$stmt->execute([$notification_id, $_SESSION['user_id']]);
header('Location: notifications.php');
exit;
}
// 标记所有为已读
if (isset($_POST['mark_all_read'])) {
$stmt = $pdo->prepare("UPDATE notifications SET is_read = TRUE WHERE user_id = ?");
$stmt->execute([$_SESSION['user_id']]);
header('Location: notifications.php');
exit;
}
// 删除通知
if (isset($_GET['delete'])) {
$notification_id = intval($_GET['delete']);
$stmt = $pdo->prepare("DELETE FROM notifications WHERE id = ? AND user_id = ?");
$stmt->execute([$notification_id, $_SESSION['user_id']]);
header('Location: notifications.php');
exit;
}
// 获取通知列表
$notifications = getUserNotifications($_SESSION['user_id'], 50);
$unreadCount = getUnreadNotificationCount($_SESSION['user_id']);
$userSettings = getUserSettings($_SESSION['user_id']);
?>
<!DOCTYPE html>
<html lang="zh-CN" data-theme="<?php echo $userSettings['dark_mode'] ? 'dark' : 'light'; ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>通知中心 - PicHost</title>
<link rel="stylesheet" href="css/style.css">
<style>
.notifications-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.notification-item {
background: white;
padding: 20px;
margin-bottom: 15px;
border-radius: 10px;
box-shadow: var(--box-shadow);
border-left: 4px solid #3498db;
transition: all 0.3s ease;
}
.notification-item.unread {
border-left-color: #e74c3c;
background: #fff9f9;
}
.notification-item.read {
opacity: 0.7;
}
.notification-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 10px;
}
.notification-title {
font-weight: bold;
margin: 0;
}
.notification-type {
padding: 2px 8px;
border-radius: 12px;
font-size: 0.75rem;
background: #f8f9fa;
color: #666;
}
.notification-message {
color: #555;
line-height: 1.5;
}
.notification-time {
color: #888;
font-size: 0.875rem;
}
.notification-actions {
display: flex;
gap: 10px;
margin-top: 10px;
}
.empty-notifications {
text-align: center;
padding: 60px 20px;
color: #666;
}
[data-theme="dark"] .notification-item {
background: var(--card-bg);
}
[data-theme="dark"] .notification-item.unread {
background: #2a1f1f;
}
.notification-announcement { border-left-color: #e74c3c; }
.notification-tips { border-left-color: #f39c12; }
.notification-feedback { border-left-color: #27ae60; }
.notification-image { border-left-color: #9b59b6; }
</style>
</head>
<body>
<?php include 'components/navbar.php'; ?>
<div class="container">
<div class="notifications-header">
<h1>通知中心</h1>
<div>
<?php if($unreadCount > 0): ?>
<form method="POST" style="display: inline;">
<button type="submit" name="mark_all_read" class="btn btn-secondary">
标记所有为已读
</button>
</form>
<?php endif; ?>
<span class="badge"><?php echo $unreadCount; ?> 条未读</span>
</div>
</div>
<?php if(empty($notifications)): ?>
<div class="empty-notifications">
<h3>📭 暂无通知</h3>
<p>您还没有收到任何通知</p>
</div>
<?php else: ?>
<div class="notifications-list">
<?php foreach($notifications as $notification): ?>
<div class="notification-item <?php echo $notification['is_read'] ? 'read' : 'unread'; ?> notification-<?php echo $notification['type_name']; ?>">
<div class="notification-header">
<h3 class="notification-title"><?php echo htmlspecialchars($notification['title']); ?></h3>
<span class="notification-type">
<?php
$typeLabels = [
'announcement' => '公告',
'tips' => '技巧',
'feedback_result' => '反馈',
'image_feedback' => '图片'
];
echo $typeLabels[$notification['type_name']] ?? $notification['type_name'];
?>
</span>
</div>
<div class="notification-message">
<?php echo nl2br(htmlspecialchars($notification['message'])); ?>
</div>
<div class="notification-footer">
<div class="notification-time">
<?php echo date('Y-m-d H:i', strtotime($notification['created_at'])); ?>
</div>
<div class="notification-actions">
<?php if(!$notification['is_read']): ?>
<a href="notifications.php?mark_read=<?php echo $notification['id']; ?>" class="btn btn-sm">
标记已读
</a>
<?php endif; ?>
<?php if($notification['related_url']): ?>
<a href="<?php echo $notification['related_url']; ?>" class="btn btn-sm btn-primary">
查看详情
</a>
<?php endif; ?>
<a href="notifications.php?delete=<?php echo $notification['id']; ?>" class="btn btn-sm btn-danger"
onclick="return confirm('确定要删除这条通知吗?')">
删除
</a>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</body>
</html>

134
register.php Normal file
View File

@@ -0,0 +1,134 @@
<?php
require_once 'config.php';
if (isset($_SESSION['user_id'])) {
header('Location: dashboard.php');
exit;
}
$error = '';
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username']);
$email = trim($_POST['email']);
$password = $_POST['password'];
$confirm_password = $_POST['confirm_password'];
if (empty($username) || empty($email) || empty($password)) {
$error = t('fill_all_fields');
} elseif ($password !== $confirm_password) {
$error = t('password_mismatch');
} elseif (strlen($password) < 6) {
$error = t('password_length_error');
} else {
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ? OR email = ?");
$stmt->execute([$username, $email]);
if ($stmt->rowCount() > 0) {
$error = t('user_exists');
} else {
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$verification_code = md5(uniqid(rand(), true));
$stmt = $pdo->prepare("INSERT INTO users (username, email, password, verification_code) VALUES (?, ?, ?, ?)");
if ($stmt->execute([$username, $email, $hashed_password, $verification_code])) {
if (sendVerificationEmail($email, $username, $verification_code)) {
$success = t('registration_success_verify');
} else {
$pdo->prepare("UPDATE users SET is_verified = 1 WHERE email = ?")->execute([$email]);
$success = t('registration_success_direct');
}
} else {
$error = t('registration_failed');
}
}
}
}
?>
<!DOCTYPE html>
<html lang="<?php echo $lang; ?>" data-theme="<?php echo $currentUserSettings['dark_mode'] ? 'dark' : 'light'; ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo t('register'); ?> - <?php echo SITE_NAME; ?></title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<?php include 'components/navbar.php'; ?>
<div class="container">
<div class="auth-container">
<div class="auth-card card">
<h2><i class="fas fa-user-plus"></i> <?php echo t('register'); ?></h2>
<?php if($error): ?>
<div class="alert alert-error">
<i class="fas fa-exclamation-triangle"></i> <?php echo $error; ?>
</div>
<?php endif; ?>
<?php if($success): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> <?php echo $success; ?>
</div>
<?php endif; ?>
<?php if(empty($success)): ?>
<form method="POST" action="">
<div class="form-group">
<label for="username">
<i class="fas fa-user"></i> <?php echo t('username'); ?>
</label>
<input type="text" id="username" name="username" required
value="<?php echo isset($_POST['username']) ? htmlspecialchars($_POST['username']) : ''; ?>"
placeholder="<?php echo t('enter_username'); ?>">
</div>
<div class="form-group">
<label for="email">
<i class="fas fa-envelope"></i> <?php echo t('email'); ?>
</label>
<input type="email" id="email" name="email" required
value="<?php echo isset($_POST['email']) ? htmlspecialchars($_POST['email']) : ''; ?>"
placeholder="<?php echo t('enter_email'); ?>">
</div>
<div class="form-group">
<label for="password">
<i class="fas fa-lock"></i> <?php echo t('password'); ?>
</label>
<input type="password" id="password" name="password" required
placeholder="<?php echo t('enter_password'); ?>">
<small><?php echo t('password_min_length'); ?></small>
</div>
<div class="form-group">
<label for="confirm_password">
<i class="fas fa-lock"></i> <?php echo t('confirm_password'); ?>
</label>
<input type="password" id="confirm_password" name="confirm_password" required
placeholder="<?php echo t('confirm_password_placeholder'); ?>">
</div>
<button type="submit" class="btn btn-primary btn-full">
<i class="fas fa-user-plus"></i> <?php echo t('register'); ?>
</button>
</form>
<?php endif; ?>
<div class="auth-links">
<p>
<?php echo t('have_account'); ?>
<a href="login.php">
<i class="fas fa-sign-in-alt"></i> <?php echo t('login_now'); ?>
</a>
</p>
</div>
</div>
</div>
</div>
</body>
</html>

172
settings.php Normal file
View File

@@ -0,0 +1,172 @@
<?php
require_once 'config.php';
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$success = '';
$error = '';
$userSettings = getUserSettings($_SESSION['user_id']);
$notificationSettings = getUserNotificationSettings($_SESSION['user_id']);
$notificationTypes = [
1 => ['name' => 'announcement', 'label' => t('system_announcements'), 'description' => t('system_announcements_desc')],
2 => ['name' => 'tips', 'label' => t('usage_tips'), 'description' => t('usage_tips_desc')],
3 => ['name' => 'feedback_result', 'label' => t('feedback_results'), 'description' => t('feedback_results_desc')],
4 => ['name' => 'image_feedback', 'label' => t('image_feedback'), 'description' => t('image_feedback_desc')]
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$dark_mode = isset($_POST['dark_mode']) ? 1 : 0;
$language = $_POST['language'] ?? 'zh-CN';
$items_per_page = intval($_POST['items_per_page'] ?? 20);
$email_notifications = isset($_POST['email_notifications']) ? 1 : 0;
$browser_notifications = isset($_POST['browser_notifications']) ? 1 : 0;
$notification_settings = [];
foreach ($notificationTypes as $type_id => $type) {
$notification_settings[$type_id] = isset($_POST['notification_' . $type_id]);
}
if ($items_per_page < 5 || $items_per_page > 100) {
$error = t('items_per_page_range_error');
} else {
$newSettings = [
'dark_mode' => $dark_mode,
'language' => $language,
'items_per_page' => $items_per_page,
'email_notifications' => $email_notifications,
'browser_notifications' => $browser_notifications
];
if (updateUserSettings($_SESSION['user_id'], $newSettings) &&
updateUserNotificationSettings($_SESSION['user_id'], $notification_settings)) {
$success = t('settings_saved');
$userSettings = $newSettings;
$notificationSettings = $notification_settings;
$_SESSION['language'] = $language;
} else {
$error = t('save_failed');
}
}
}
?>
<!DOCTYPE html>
<html lang="<?php echo $lang; ?>" data-theme="<?php echo $userSettings['dark_mode'] ? 'dark' : 'light'; ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo t('settings'); ?> - <?php echo SITE_NAME; ?></title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<?php include 'components/navbar.php'; ?>
<div class="container">
<h1><i class="fas fa-sliders-h"></i> <?php echo t('settings'); ?></h1>
<?php if($success): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle"></i> <?php echo $success; ?>
</div>
<?php endif; ?>
<?php if($error): ?>
<div class="alert alert-error">
<i class="fas fa-exclamation-triangle"></i> <?php echo $error; ?>
</div>
<?php endif; ?>
<div class="settings-container">
<form method="POST" action="">
<div class="setting-group card">
<h3><i class="fas fa-palette"></i> <?php echo t('appearance_settings'); ?></h3>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" name="dark_mode" <?php echo $userSettings['dark_mode'] ? 'checked' : ''; ?>>
<span class="checkmark"></span>
<i class="fas fa-moon"></i> <?php echo t('enable_dark_mode'); ?>
</label>
</div>
</div>
<div class="setting-group card">
<h3><i class="fas fa-desktop"></i> <?php echo t('display_settings'); ?></h3>
<div class="form-group">
<label for="items_per_page">
<i class="fas fa-list"></i> <?php echo t('items_per_page'); ?>
</label>
<select id="items_per_page" name="items_per_page">
<option value="10" <?php echo $userSettings['items_per_page'] == 10 ? 'selected' : ''; ?>>10</option>
<option value="20" <?php echo $userSettings['items_per_page'] == 20 ? 'selected' : ''; ?>>20</option>
<option value="30" <?php echo $userSettings['items_per_page'] == 30 ? 'selected' : ''; ?>>30</option>
<option value="50" <?php echo $userSettings['items_per_page'] == 50 ? 'selected' : ''; ?>>50</option>
</select>
</div>
</div>
<div class="setting-group card">
<h3><i class="fas fa-bell"></i> <?php echo t('notification_settings'); ?></h3>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" name="email_notifications" <?php echo $userSettings['email_notifications'] ? 'checked' : ''; ?>>
<span class="checkmark"></span>
<i class="fas fa-envelope"></i> <?php echo t('enable_email_notifications'); ?>
</label>
<small><?php echo t('email_notifications_desc'); ?></small>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" name="browser_notifications" <?php echo $userSettings['browser_notifications'] ? 'checked' : ''; ?>>
<span class="checkmark"></span>
<i class="fas fa-bell"></i> <?php echo t('enable_browser_notifications'); ?>
</label>
<small><?php echo t('browser_notifications_desc'); ?></small>
</div>
<div class="notification-types">
<h4><i class="fas fa-list-alt"></i> <?php echo t('notification_types'); ?></h4>
<?php foreach($notificationTypes as $type_id => $type): ?>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" name="notification_<?php echo $type_id; ?>"
<?php echo ($notificationSettings[$type['name']] ?? true) ? 'checked' : ''; ?>>
<span class="checkmark"></span>
<strong><?php echo $type['label']; ?></strong>
<br>
<small style="margin-left: 25px; color: #666;"><?php echo $type['description']; ?></small>
</label>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="setting-group card">
<h3><i class="fas fa-language"></i> <?php echo t('language_settings'); ?></h3>
<div class="form-group">
<label for="language">
<i class="fas fa-globe"></i> <?php echo t('interface_language'); ?>
</label>
<select id="language" name="language">
<option value="zh-CN" <?php echo $userSettings['language'] == 'zh-CN' ? 'selected' : ''; ?>><?php echo t('simplified_chinese'); ?></option>
<option value="en" <?php echo $userSettings['language'] == 'en' ? 'selected' : ''; ?>><?php echo t('english'); ?></option>
</select>
</div>
</div>
<button type="submit" class="btn btn-primary btn-full">
<i class="fas fa-save"></i> <?php echo t('save_settings'); ?>
</button>
</form>
</div>
</div>
</body>
</html>