Files
freeshop/admin/announcements.php
T
2026-08-14 10:55:06 +08:00

146 lines
6.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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 ? '编辑公告 #' . (int)$edit['id'] : '发布新公告' ?></h3>
<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="https://markdown.com.cn/cheat-sheet.html">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(); ?>