mirror of
https://gh.wpcy.net/https://github.com/UISNBLOON/TrackICP.git
synced 2026-05-07 15:22:28 +08:00
608 lines
No EOL
22 KiB
PHP
608 lines
No EOL
22 KiB
PHP
<!DOCTYPE html>
|
|
<?php
|
|
session_start();
|
|
require_once '../auth_check.php';
|
|
checkAdminAuth();
|
|
$csrf_token = generateCSRFToken();
|
|
|
|
// 加载配置
|
|
$config = include '../config.php';
|
|
|
|
// 数据库连接函数
|
|
function getDatabaseConnection() {
|
|
global $config;
|
|
try {
|
|
if ($config['database_type'] === 'mysql') {
|
|
$dsn = "mysql:host={$config['database_config']['host']};port={$config['database_config']['port']};dbname={$config['database_config']['name']};charset=utf8mb4";
|
|
return new PDO($dsn, $config['database_config']['user'], $config['database_config']['password']);
|
|
} else if ($config['database_type'] === 'sqlite') {
|
|
$dsn = "sqlite:{$config['database_config']['path']}";
|
|
return new PDO($dsn);
|
|
}
|
|
} catch (PDOException $e) {
|
|
die('数据库连接失败: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// 连接数据库
|
|
$pdo = getDatabaseConnection();
|
|
|
|
// 获取网站信息
|
|
$stmt = $pdo->query("SELECT name, description FROM site_info LIMIT 1");
|
|
$siteInfo = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
// 如果找不到网站信息,使用配置文件中的默认值
|
|
if (!$siteInfo) {
|
|
$siteInfo = [
|
|
'name' => $config['site_name'] ?? '二次元网站备案系统',
|
|
'description' => $config['site_description'] ?? '管理和审核网站备案申请'
|
|
];
|
|
}
|
|
|
|
// 处理备案状态更新
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_status') {
|
|
// 验证CSRF令牌
|
|
verifyCSRFToken($_POST['csrf_token'] ?? '');
|
|
|
|
$id = $_POST['id'];
|
|
$status = $_POST['status'];
|
|
$reason = $_POST['reason'] ?? '';
|
|
|
|
try {
|
|
// 开始事务
|
|
$pdo->beginTransaction();
|
|
|
|
// 获取备案信息
|
|
$stmt = $pdo->prepare("SELECT * FROM registrations WHERE id = ?");
|
|
$stmt->execute([$id]);
|
|
$registration = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$registration) {
|
|
throw new Exception('未找到该备案申请');
|
|
}
|
|
|
|
// 生成备案编号(如果通过审核)
|
|
$registrationNumber = $registration['registration_number'];
|
|
if ($status === 'approved' && empty($registrationNumber)) {
|
|
$registrationNumber = str_pad(rand(10000000, 99999999), 8, '0', STR_PAD_LEFT);
|
|
}
|
|
|
|
// 更新备案状态
|
|
$stmt = $pdo->prepare("UPDATE registrations SET status = ?, reason = ?, processed_at = NOW(), registration_number = ? WHERE id = ?");
|
|
$stmt->execute([$status, $reason, $registrationNumber, $id]);
|
|
|
|
// 如果审核通过,发送邮件
|
|
if ($status === 'approved') {
|
|
// 加载邮件工具
|
|
require_once '../email_utils.php';
|
|
|
|
// 更新备案信息中的处理日期和备案编号
|
|
$registration['status'] = 'approved';
|
|
$registration['processed_at'] = date('Y-m-d H:i:s');
|
|
$registration['registration_number'] = $registrationNumber;
|
|
|
|
// 确保contact_email字段存在
|
|
if (!isset($registration['contact_email']) || empty($registration['contact_email'])) {
|
|
throw new Exception('缺少联系邮箱,无法发送审核通过邮件');
|
|
}
|
|
|
|
try {
|
|
// 创建邮件工具实例
|
|
$emailUtils = new EmailUtils($pdo);
|
|
// 发送审核通过邮件
|
|
$emailUtils->sendApprovalEmail($registration);
|
|
} catch (Exception $e) {
|
|
// 记录邮件发送失败,但不影响审核流程
|
|
error_log('发送审核通过邮件失败: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// 提交事务
|
|
$pdo->commit();
|
|
|
|
header("Location: admin_dashboard.php");
|
|
exit();
|
|
} catch (PDOException $e) {
|
|
// 回滚事务
|
|
$pdo->rollBack();
|
|
die('更新备案状态失败: ' . $e->getMessage());
|
|
} catch (Exception $e) {
|
|
// 回滚事务
|
|
$pdo->rollBack();
|
|
die('处理失败: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// 确定要显示的备案类型
|
|
$view = $_GET['view'] ?? 'all';
|
|
|
|
// 根据视图类型获取备案申请
|
|
if ($view === 'pending') {
|
|
// 获取待审核的备案申请
|
|
$stmt = $pdo->prepare("SELECT * FROM registrations WHERE status = 'pending' ORDER BY created_at DESC");
|
|
$stmt->execute();
|
|
$registrations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$title = '待审核备案申请';
|
|
} else if ($view === 'approved') {
|
|
// 获取已通过的备案申请
|
|
$stmt = $pdo->prepare("SELECT * FROM registrations WHERE status = 'approved' ORDER BY processed_at DESC");
|
|
$stmt->execute();
|
|
$registrations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$title = '已通过备案申请';
|
|
} else if ($view === 'rejected') {
|
|
// 获取已拒绝的备案申请
|
|
$stmt = $pdo->prepare("SELECT * FROM registrations WHERE status = 'rejected' ORDER BY processed_at DESC");
|
|
$stmt->execute();
|
|
$registrations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$title = '已拒绝备案申请';
|
|
} else {
|
|
// 获取所有备案申请
|
|
$stmt = $pdo->prepare("SELECT * FROM registrations ORDER BY created_at DESC");
|
|
$stmt->execute();
|
|
$registrations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$title = '所有备案申请';
|
|
}
|
|
|
|
// 确保registrations表存在
|
|
function ensureRegistrationsTableExists($pdo) {
|
|
try {
|
|
// 根据数据库类型选择自增关键字
|
|
global $config;
|
|
$auto_increment = ($config['database_type'] === 'mysql') ? 'AUTO_INCREMENT' : 'AUTOINCREMENT';
|
|
$int_type = ($config['database_type'] === 'mysql') ? 'INT' : 'INTEGER';
|
|
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS registrations (
|
|
id $int_type PRIMARY KEY $auto_increment,
|
|
website_name VARCHAR(255) NOT NULL,
|
|
website_url VARCHAR(255) NOT NULL,
|
|
contact_person VARCHAR(100) NOT NULL,
|
|
contact_email VARCHAR(255) NOT NULL,
|
|
contact_phone VARCHAR(255) NOT NULL,
|
|
website_category VARCHAR(100) NOT NULL,
|
|
website_description TEXT NOT NULL,
|
|
status VARCHAR(20) DEFAULT 'pending',
|
|
reason TEXT,
|
|
registration_number VARCHAR(50),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
processed_at TIMESTAMP
|
|
)");
|
|
} catch (PDOException $e) {
|
|
die('创建registrations表失败: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// 确保site_info表存在
|
|
function ensureSiteInfoTableExists($pdo) {
|
|
try {
|
|
// 根据数据库类型选择自增关键字
|
|
global $config;
|
|
$auto_increment = ($config['database_type'] === 'mysql') ? 'AUTO_INCREMENT' : 'AUTOINCREMENT';
|
|
$int_type = ($config['database_type'] === 'mysql') ? 'INT' : 'INTEGER';
|
|
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS site_info (
|
|
id $int_type PRIMARY KEY $auto_increment,
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT NOT NULL,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)");
|
|
} catch (PDOException $e) {
|
|
die('创建site_info表失败: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// 确保email_config表存在
|
|
function ensureEmailConfigTableExists($pdo) {
|
|
try {
|
|
// 根据数据库类型选择自增关键字
|
|
global $config;
|
|
$auto_increment = ($config['database_type'] === 'mysql') ? 'AUTO_INCREMENT' : 'AUTOINCREMENT';
|
|
$int_type = ($config['database_type'] === 'mysql') ? 'INT' : 'INTEGER';
|
|
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS email_config (
|
|
id $int_type PRIMARY KEY $auto_increment,
|
|
smtp_host VARCHAR(255) NOT NULL,
|
|
smtp_port INTEGER NOT NULL,
|
|
smtp_username VARCHAR(255) NOT NULL,
|
|
smtp_password VARCHAR(255) NOT NULL,
|
|
smtp_encryption VARCHAR(10) NOT NULL,
|
|
from_email VARCHAR(255) NOT NULL,
|
|
from_name VARCHAR(255) NOT NULL,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)");
|
|
} catch (PDOException $e) {
|
|
die('创建email_config表失败: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// 确保表存在
|
|
ensureRegistrationsTableExists($pdo);
|
|
ensureSiteInfoTableExists($pdo);
|
|
ensureEmailConfigTableExists($pdo);
|
|
?>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>管理员控制面板 - <?php echo $siteInfo['name']; ?></title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
body {
|
|
background-color: #f0f2f5;
|
|
color: #333;
|
|
line-height: 1.6;
|
|
}
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
}
|
|
.header-frosted {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
background: rgba(255, 255, 255, 0.7);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
color: #333;
|
|
padding: 15px 20px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
z-index: 1000;
|
|
}
|
|
.header-nav {
|
|
display: flex;
|
|
gap: 20px;
|
|
}
|
|
.header-nav span {
|
|
cursor: pointer;
|
|
color: #7873f5;
|
|
font-weight: bold;
|
|
transition: color 0.3s ease;
|
|
}
|
|
.header-nav span:hover {
|
|
color: #605acf;
|
|
}
|
|
header {
|
|
background: linear-gradient(135deg, #ff6ec7, #7873f5);
|
|
color: white;
|
|
padding: 80px 0 40px;
|
|
text-align: center;
|
|
border-radius: 10px;
|
|
margin-bottom: 30px;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
margin-top: 60px;
|
|
}
|
|
h1 {
|
|
font-size: 2rem;
|
|
margin-bottom: 10px;
|
|
}
|
|
.card {
|
|
background: white;
|
|
border-radius: 10px;
|
|
padding: 30px;
|
|
margin-bottom: 30px;
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
|
|
}
|
|
h2 {
|
|
color: #7873f5;
|
|
margin-bottom: 20px;
|
|
padding-bottom: 10px;
|
|
border-bottom: 2px solid #f0f0f0;
|
|
}
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-bottom: 20px;
|
|
}
|
|
th, td {
|
|
padding: 12px 15px;
|
|
text-align: left;
|
|
border-bottom: 1px solid #ddd;
|
|
}
|
|
th {
|
|
background-color: #f8f9fa;
|
|
font-weight: bold;
|
|
}
|
|
tr:hover {
|
|
background-color: #f5f5f5;
|
|
}
|
|
.status {
|
|
display: inline-block;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
font-size: 0.8rem;
|
|
font-weight: bold;
|
|
}
|
|
.status-pending {
|
|
background-color: #fff3cd;
|
|
color: #856404;
|
|
}
|
|
.status-approved {
|
|
background-color: #d4edda;
|
|
color: #155724;
|
|
}
|
|
.status-rejected {
|
|
background-color: #f8d7da;
|
|
color: #721c24;
|
|
}
|
|
.btn {
|
|
display: inline-block;
|
|
background: #7873f5;
|
|
color: white;
|
|
padding: 8px 15px;
|
|
border-radius: 4px;
|
|
text-decoration: none;
|
|
font-weight: bold;
|
|
transition: background 0.3s ease;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 0.9rem;
|
|
}
|
|
.btn:hover {
|
|
background: #605acf;
|
|
}
|
|
.btn-success {
|
|
background: #28a745;
|
|
}
|
|
.btn-success:hover {
|
|
background: #218838;
|
|
}
|
|
.btn-danger {
|
|
background: #dc3545;
|
|
}
|
|
.btn-danger:hover {
|
|
background: #c82333;
|
|
}
|
|
.action-buttons {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
.modal {
|
|
display: none;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: rgba(0,0,0,0.5);
|
|
z-index: 1001;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.modal-content {
|
|
background-color: white;
|
|
padding: 30px;
|
|
border-radius: 10px;
|
|
width: 100%;
|
|
max-width: 500px;
|
|
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
|
|
}
|
|
.modal h3 {
|
|
margin-bottom: 20px;
|
|
color: #7873f5;
|
|
}
|
|
.form-group {
|
|
margin-bottom: 20px;
|
|
}
|
|
label {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
font-weight: bold;
|
|
color: #555;
|
|
}
|
|
textarea {
|
|
width: 100%;
|
|
padding: 10px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
min-height: 100px;
|
|
resize: vertical;
|
|
}
|
|
.modal-footer {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 10px;
|
|
margin-top: 20px;
|
|
}
|
|
.logout-btn {
|
|
background: #dc3545;
|
|
color: white;
|
|
border: none;
|
|
padding: 8px 15px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-weight: bold;
|
|
transition: background 0.3s ease;
|
|
}
|
|
.logout-btn:hover {
|
|
background: #c82333;
|
|
}
|
|
.search-container {
|
|
margin-bottom: 20px;
|
|
}
|
|
.search-input {
|
|
padding: 10px;
|
|
width: 300px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
font-size: 1rem;
|
|
}
|
|
.search-btn {
|
|
padding: 10px 15px;
|
|
background: #7873f5;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header-frosted">
|
|
<h3><?php echo $siteInfo['name']; ?> - 管理员面板</h3>
|
|
<div class="header-nav">
|
|
<span onclick="window.location.href='admin_dashboard.php'">控制面板</span>
|
|
<span onclick="window.location.href='admin_dashboard.php?view=all'">所有备案</span>
|
|
<span onclick="window.location.href='admin_dashboard.php?view=pending'">待审核备案</span>
|
|
<span onclick="window.location.href='add_registration.php'">添加备案</span>
|
|
<span onclick="window.location.href='settings.php'">系统设置</span>
|
|
<button class="logout-btn" onclick="window.location.href='admin_login.php?action=logout'">退出登录</button>
|
|
</div>
|
|
</div>
|
|
<div class="container">
|
|
<header>
|
|
<h1><?php echo $siteInfo['name']; ?> - 管理员控制面板</h1>
|
|
<p><?php echo $siteInfo['description']; ?></p>
|
|
</header>
|
|
|
|
<div class="card">
|
|
<h2><?php echo $title; ?></h2>
|
|
|
|
<div class="search-container">
|
|
<input type="text" class="search-input" id="searchInput" placeholder="搜索网站名称或URL...">
|
|
<button class="search-btn" onclick="searchRegistrations()">搜索</button>
|
|
</div>
|
|
|
|
<table id="registrationsTable">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>网站名称</th>
|
|
<th>网站URL</th>
|
|
<th>联系人</th>
|
|
<th>提交时间</th>
|
|
<th>状态</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($registrations as $registration): ?>
|
|
<tr>
|
|
<td><?php echo $registration['id']; ?></td>
|
|
<td><?php echo htmlspecialchars($registration['website_name']); ?></td>
|
|
<td><?php echo htmlspecialchars($registration['website_url']); ?></td>
|
|
<td><?php echo htmlspecialchars($registration['contact_person']); ?></td>
|
|
<td><?php echo $registration['created_at']; ?></td>
|
|
<td>
|
|
<span class="status status-<?php echo $registration['status']; ?>">
|
|
<?php
|
|
switch ($registration['status']) {
|
|
case 'pending': echo '待审核'; break;
|
|
case 'approved': echo '已通过'; break;
|
|
case 'rejected': echo '已拒绝'; break;
|
|
}
|
|
?>
|
|
</span>
|
|
</td>
|
|
<td class="action-buttons">
|
|
<?php if ($registration['status'] === 'pending'): ?>
|
|
<button class="btn btn-success" onclick="openModal(<?php echo $registration['id']; ?>, 'approved')">通过</button>
|
|
<button class="btn btn-danger" onclick="openModal(<?php echo $registration['id']; ?>, 'rejected')">拒绝</button>
|
|
<?php else: ?>
|
|
<button class="btn" onclick="showDetails(<?php echo $registration['id']; ?>)">详情</button>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 审核操作模态框 -->
|
|
<div id="actionModal" class="modal">
|
|
<div class="modal-content">
|
|
<h3 id="modalTitle">审核操作</h3>
|
|
<form method="post" id="actionForm">
|
|
<input type="hidden" name="action" value="update_status">
|
|
<input type="hidden" name="csrf_token" value="<?php echo $csrf_token; ?>">
|
|
<input type="hidden" name="id" id="registrationId">
|
|
<input type="hidden" name="status" id="actionStatus">
|
|
|
|
<div class="form-group" id="reasonGroup">
|
|
<label for="reason">审核说明</label>
|
|
<textarea id="reason" name="reason" placeholder="请输入审核说明(拒绝时必填)"></textarea>
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-danger" onclick="closeModal()">取消</button>
|
|
<button type="submit" class="btn" id="submitBtn">提交</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// 模态框相关操作
|
|
const modal = document.getElementById('actionModal');
|
|
const actionForm = document.getElementById('actionForm');
|
|
const registrationIdInput = document.getElementById('registrationId');
|
|
const actionStatusInput = document.getElementById('actionStatus');
|
|
const modalTitle = document.getElementById('modalTitle');
|
|
const reasonGroup = document.getElementById('reasonGroup');
|
|
const submitBtn = document.getElementById('submitBtn');
|
|
|
|
function openModal(id, status) {
|
|
registrationIdInput.value = id;
|
|
actionStatusInput.value = status;
|
|
|
|
if (status === 'approved') {
|
|
modalTitle.textContent = '通过备案申请';
|
|
reasonGroup.style.display = 'block';
|
|
submitBtn.className = 'btn btn-success';
|
|
} else {
|
|
modalTitle.textContent = '拒绝备案申请';
|
|
reasonGroup.style.display = 'block';
|
|
submitBtn.className = 'btn btn-danger';
|
|
}
|
|
|
|
modal.style.display = 'flex';
|
|
}
|
|
|
|
function closeModal() {
|
|
modal.style.display = 'none';
|
|
}
|
|
|
|
// 点击模态框外部关闭
|
|
window.onclick = function(event) {
|
|
if (event.target === modal) {
|
|
closeModal();
|
|
}
|
|
}
|
|
|
|
// 搜索功能
|
|
function searchRegistrations() {
|
|
const input = document.getElementById('searchInput');
|
|
const filter = input.value.toUpperCase();
|
|
const table = document.getElementById('registrationsTable');
|
|
const tr = table.getElementsByTagName('tr');
|
|
|
|
for (let i = 1; i < tr.length; i++) {
|
|
const td1 = tr[i].getElementsByTagName('td')[1]; // 网站名称
|
|
const td2 = tr[i].getElementsByTagName('td')[2]; // 网站URL
|
|
let txtValue1 = td1.textContent || td1.innerText;
|
|
let txtValue2 = td2.textContent || td2.innerText;
|
|
|
|
if (txtValue1.toUpperCase().indexOf(filter) > -1 || txtValue2.toUpperCase().indexOf(filter) > -1) {
|
|
tr[i].style.display = '';
|
|
} else {
|
|
tr[i].style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
|
|
// 显示详情功能
|
|
function showDetails(id) {
|
|
alert('备案ID: ' + id + ' 的详细信息\n此功能将在后续版本中完善');
|
|
// 实际应用中可以跳转到详情页或显示更详细的模态框
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|