初始化版本

This commit is contained in:
LL
2025-11-18 14:18:28 +08:00
commit 3c348195b7
23 changed files with 2837 additions and 0 deletions

180
review_texts.php Normal file
View File

@@ -0,0 +1,180 @@
<?php
// 文案审核页面:查看 texts_pending 中的待处理文案,执行通过/拒绝
session_start();
$ADMIN_PASSWORD = 'my123123';
// 退出登录
if (isset($_GET['logout'])) {
unset($_SESSION['admin_ok']);
header('Location: review_texts.php');
exit;
}
// 登录处理
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['password'])) {
$pwd = trim($_POST['password'] ?? '');
if ($pwd === $ADMIN_PASSWORD) {
$_SESSION['admin_ok'] = true;
header('Location: review_texts.php');
exit;
} else {
$login_error = '密码错误,请重试';
}
}
// 若未登录,显示登录界面
if (empty($_SESSION['admin_ok'])) {
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>管理员登录 - 文案审核</title>
<link rel="stylesheet" href="assets/style.css" />
<style>
.login-card { max-width: 480px; margin: 60px auto; border:2px solid #e33; border-radius:12px; padding:20px; background:#fff; }
.login-card h1 { margin:0 0 12px; font-size:20px; }
.login-card .field { display:flex; flex-direction:column; gap:8px; }
.login-card input { padding:10px 12px; border:1px solid #ddd; border-radius:8px; }
.login-card .btn { background:#e33; color:#fff; border:none; padding:10px 18px; border-radius:22px; cursor:pointer; }
.login-card .err { color:#c00; font-size:13px; margin-top:8px; }
</style>
</head>
<body>
<div class="page">
<header class="menu">
<div class="menu__logo">审核登录</div>
<nav aria-label="主菜单">
<ul class="menu__nav">
<li><a class="menu__link" href="index.php">返回首页</a></li>
</ul>
</nav>
</header>
<main class="login-card" aria-label="管理员登录">
<h1>请输入管理员密码</h1>
<form method="post">
<div class="field">
<label for="password">密码</label>
<input id="password" name="password" type="password" placeholder="输入管理员密码" required />
</div>
<div style="margin-top:12px;">
<button class="btn" type="submit">登录</button>
</div>
<?php if (!empty($login_error)): ?>
<div class="err"><?php echo htmlspecialchars($login_error); ?></div>
<?php endif; ?>
</form>
</main>
</div>
</body>
</html>
<?php
exit;
}
$pendingDir = __DIR__ . '/texts_pending';
$files = [];
if (is_dir($pendingDir)) {
foreach (scandir($pendingDir) as $f) {
if ($f === '.' || $f === '..') continue;
if (preg_match('/\.json$/i', $f)) {
$files[] = $f;
}
}
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文案审核</title>
<link rel="stylesheet" href="assets/style.css" />
<style>
.review-page { max-width: 1100px; margin: 24px auto; }
.review-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:12px; }
.list { display:grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap:12px; }
.card { border:2px solid #e33; border-radius:10px; padding:12px; background:#fff; }
.card h3 { margin:0 0 8px; font-size:16px; }
.card pre { white-space:pre-wrap; font-size:13px; color:#333; }
.meta { font-size: 12px; color:#666; margin-top:6px; }
.actions { display:flex; gap:8px; margin-top:8px; }
.btn { padding:6px 12px; border:none; border-radius:16px; cursor:pointer; }
.btn.approve { background:#2ebd59; color:#fff; }
.btn.reject { background:#999; color:#fff; }
</style>
</head>
<body>
<div class="page review-page">
<header class="menu">
<div class="menu__logo">文案审核</div>
<nav aria-label="主菜单">
<ul class="menu__nav">
<li><a class="menu__link" href="index.php">返回首页</a></li>
<li><a class="menu__link" href="review_texts.php?logout=1">退出登录</a></li>
</ul>
</nav>
</header>
<div class="review-head">
<h1 style="margin:0;font-size:18px;">待审核文案(<?php echo count($files); ?></h1>
</div>
<section class="list" id="pendingList">
<?php if (!$files): ?>
<p>当前无待审核文案。</p>
<?php else: foreach ($files as $f):
$metaPath = $pendingDir . '/' . $f;
$meta = is_file($metaPath) ? json_decode(@file_get_contents($metaPath), true) : [];
$title = !empty($meta['title']) ? $meta['title'] : '(无标题)';
$content = !empty($meta['content']) ? $meta['content'] : '';
$preview = $content;
if (function_exists('mb_substr')) {
$preview = mb_substr($content, 0, 200);
} else {
$preview = substr($content, 0, 200);
}
?>
<div class="card" data-file="<?php echo htmlspecialchars($f); ?>">
<h3><?php echo htmlspecialchars($title); ?></h3>
<pre><?php echo htmlspecialchars($preview); ?><?php echo (strlen($content) > strlen($preview)) ? '…' : ''; ?></pre>
<div class="meta">
<div>文件:<?php echo htmlspecialchars($f); ?></div>
<?php if (!empty($meta['uploaded_at'])): ?><div>投稿时间:<?php echo htmlspecialchars($meta['uploaded_at']); ?></div><?php endif; ?>
</div>
<div class="actions">
<button class="btn approve">通过</button>
<button class="btn reject">拒绝</button>
</div>
</div>
<?php endforeach; endif; ?>
</section>
</div>
<script>
const list = document.getElementById('pendingList');
function send(action, file, password) {
const fd = new FormData();
fd.append('action', action);
fd.append('file', file);
fd.append('password', password);
return fetch('api/review_text_action.php', { method: 'POST', body: fd }).then(r=>r.json());
}
list?.addEventListener('click', async (e) => {
const btn = e.target.closest('button');
if (!btn) return;
const card = e.target.closest('.card');
const file = card?.dataset?.file;
if (!file) return;
const action = btn.classList.contains('approve') ? 'approve' : 'reject';
btn.disabled = true;
const res = await send(action, file, '').catch(()=>({ok:false,msg:'请求失败'}));
btn.disabled = false;
alert(res.msg || '操作完成');
if (res.ok) {
card.remove();
}
});
</script>
</body>
</html>
<?php ?>