文件
freeshop/admin/announcements.php
2026-08-16 17:03:10 +08:00

134 行
6.5 KiB
PHP

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
<?php
require __DIR__ . '/../includes/init.php';
requireStaff();
require '_common.php';
$isAdmin = isAdminStaff();
$db = db();
$msg = '';
$err = '';
if (!$isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST') {
$err = '客服账号仅可查看,如需操作请联系管理员。';
}
if (isset($_POST['delete'])) {
verifyCsrf();
$id = (int) ($_POST['delete'] ?? 0);
$db->prepare('DELETE FROM ' . tn('announcements') . ' WHERE id = ?')->execute([$id]);
$msg = '已删除这条公告。';
}
if (isset($_POST['save'])) {
verifyCsrf();
$id = (int) ($_POST['id'] ?? 0);
$title = trim($_POST['title'] ?? '');
$content = trim($_POST['content'] ?? '');
$pinned = isset($_POST['pinned']) ? 1 : 0;
$status = isset($_POST['status']) ? 1 : 0;
if ($title === '') $err = '请填写公告标题。';
elseif ($content === '') $err = '请填写公告内容。';
if ($err === '') {
if ($id > 0) {
$db->prepare('UPDATE ' . tn('announcements') . ' SET title=?, content=?, pinned=?, status=? WHERE id=?')
->execute([$title, $content, $pinned, $status, $id]);
$msg = '公告已更新!';
} else {
$db->prepare('INSERT INTO ' . tn('announcements') . ' (title, content, pinned, status, created_at) VALUES (?,?,?,?,NOW())')
->execute([$title, $content, $pinned, $status]);
$msg = '公告已发布!';
}
}
}
$edit = null;
if (isset($_GET['edit'])) {
$stmt = $db->prepare('SELECT * FROM ' . tn('announcements') . ' WHERE id = ?');
$stmt->execute([(int) $_GET['edit']]);
$edit = $stmt->fetch();
}
$showForm = ($edit !== null) || isset($_GET['act']) && $_GET['act'] === 'add';
$list = $db->query('SELECT * FROM ' . tn('announcements') . ' ORDER BY pinned DESC, created_at DESC')->fetchAll();
adminHeader('公告中心', 'announcements');
?>
<h1 class="page-title"><i class="fas fa-bullhorn"></i> 公告中心</h1>
<?php if ($msg): ?><p class="banner-ok"><i class="fas fa-check-circle"></i> <?= h($msg) ?></p><?php endif; ?>
<?php if ($err): ?><p class="form-err"><?= h($err) ?></p><?php endif; ?>
<?php if ($showForm): ?>
<div class="panel">
<h3><?= $edit ? '编辑公告
<form method="post" action="" class="grid-form">
<?= csrfField() ?>
<input type="hidden" name="id" value="<?= $edit ? (int)$edit['id'] : 0 ?>">
<label class="span2">
<span>公告标题 <b style="color: red;">*</b></span>
<input type="text" name="title" value="<?= $edit ? h($edit['title']) : '' ?>" required>
</label>
<label class="span2">
<span>公告内容 <b style="color: red;">*</b>(支持 <a href="">Markdown 语法</a></span>
<textarea id="annContent" name="content" rows="8" required><?= $edit ? h($edit['content']) : '' ?></textarea>
</label>
<div class="span2 ann-preview-wrap">
<div class="ann-preview-bar">
<strong>实时预览</strong>
<button type="button" class="btn btn-ghost btn-sm" id="annPreviewToggle">显示 / 隐藏预览</button>
</div>
<div class="ann-detail-body ann-preview" id="annPreview"></div>
</div>
<label class="checkbox"><input type="checkbox" name="pinned" <?= $edit && !empty($edit['pinned']) ? 'checked' : '' ?>> 置顶</label>
<label class="checkbox"><input type="checkbox" name="status" <?= !$edit || !empty($edit['status']) ? 'checked' : '' ?>> 前台显示</label>
<div class="form-actions span2">
<button type="submit" name="save" class="btn btn-primary"><i class="fas fa-save"></i> 保存</button>
<a href="announcements.php" class="btn btn-ghost">取消</a>
</div>
</form>
</div>
<?php endif; ?>
<div class="panel">
<div class="panel-head">
<h3>公告列表(共 <?= count($list) ?> 条)</h3>
<?php if (!$showForm): ?><a href="announcements.php?act=add" class="btn btn-primary"><i class="fas fa-plus"></i> 发布公告</a><?php endif; ?>
</div>
<?php if (empty($list)): ?>
<p class="empty">还没有公告,点上方「发布公告」。</p>
<?php else: ?>
<table class="data-table">
<thead><tr><th>ID</th><th>标题</th><th>置顶</th><th>显示</th><th>时间</th><th>操作</th></tr></thead>
<tbody>
<?php foreach ($list as $a): ?>
<tr>
<td><?= (int)$a['id'] ?></td>
<td><?= h($a['title']) ?></td>
<td><?= !empty($a['pinned']) ? '<span class="badge-on">置顶</span>' : '<span class="badge-off">否</span>' ?></td>
<td><?= !empty($a['status']) ? '<span class="badge-on">显示</span>' : '<span class="badge-off">隐藏</span>' ?></td>
<td><?= date('m-d H:i', strtotime($a['created_at'])) ?></td>
<td class="row-actions">
<a href="../announcement.php?id=<?= (int)$a['id'] ?>" class="mini-btn" target="_blank" title="前台预览"><i class="fas fa-eye"></i></a>
<a href="announcements.php?edit=<?= (int)$a['id'] ?>" class="mini-btn"><i class="fas fa-edit"></i></a>
<form method="post" action="" style="display:inline" onsubmit="return confirm('确定删除该公告?');">
<?= csrfField() ?>
<button type="submit" name="delete" value="<?= (int)$a['id'] ?>" class="mini-btn danger"><i class="fas fa-trash"></i></button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
<?php
$mv = file_exists(__DIR__ . '/../assets/marked.js') ? filemtime(__DIR__ . '/../assets/marked.js') : time();
?>
<script src="../assets/marked.js?v=<?= $mv ?>"></script>
<script>
(function () {
var ta = document.getElementById('annContent');
var pv = document.getElementById('annPreview');
if (!ta || !pv || !window.marked) return;
function render() {
try { pv.innerHTML = marked.parse(ta.value || ''); }
catch (e) { pv.textContent = ta.value; }
}
ta.addEventListener('input', render);
render();
var btn = document.getElementById('annPreviewToggle');
if (btn) btn.addEventListener('click', function () { pv.hidden = !pv.hidden; });
})();
</script>
<?php adminFooter(); ?>