203 lines
10 KiB
PHP
203 lines
10 KiB
PHP
<?php
|
|
// 后台:管理员 / 客服账户管理(增删改角色 + 终极管理员保护)
|
|
require __DIR__ . '/../includes/init.php';
|
|
requireStaff();
|
|
require '_common.php';
|
|
$isAdmin = isAdminStaff();
|
|
$me = currentStaff();
|
|
$db = db();
|
|
$msg = '';
|
|
$err = '';
|
|
|
|
// 客服只读
|
|
if (!$isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$err = '客服账号仅可查看,如需操作请联系管理员。';
|
|
}
|
|
|
|
// ─── 编辑角色(admin ↔ cs)────
|
|
if (isset($_POST['edit_role']) && $isAdmin) {
|
|
verifyCsrf();
|
|
$id = (int) ($_POST['edit_role'] ?? 0);
|
|
$role = trim($_POST['new_role'] ?? '');
|
|
$role = in_array($role, ['admin', 'cs'], true) ? $role : '';
|
|
|
|
if ($id <= 0 || $role === '') {
|
|
$err = '参数不合法。';
|
|
} elseif ($id === (int) $me['id']) {
|
|
$err = '不能修改当前登录账号的角色。';
|
|
} elseif ($id === 1) {
|
|
$err = '不能修改终极管理员(ID=1)的角色。';
|
|
} else {
|
|
$row = $db->prepare('SELECT id, role, is_admin FROM ' . tn('users') . ' WHERE id = ? AND role IN (\'admin\',\'cs\')')->execute([$id])->fetch();
|
|
if (!$row) {
|
|
$err = '账号不存在。';
|
|
} else {
|
|
$newIsAdmin = ($role === 'admin') ? 1 : 0;
|
|
$db->prepare('UPDATE ' . tn('users') . ' SET role = ?, is_admin = ? WHERE id = ?')
|
|
->execute([$role, $newIsAdmin, $id]);
|
|
$msg = '已将账号 #' . $id . ' 角色改为「' . ($role === 'admin' ? '管理员' : '客服') . '」。';
|
|
}
|
|
}
|
|
}
|
|
|
|
// ─── 删除 ──
|
|
if (isset($_POST['delete']) && $isAdmin) {
|
|
verifyCsrf();
|
|
$id = (int) ($_POST['delete'] ?? 0);
|
|
if ($id === (int) $me['id']) {
|
|
$err = '不能删除当前登录的账号。';
|
|
} elseif ($id === 1) {
|
|
$err = '不能删除终极管理员(ID=1),该账号受系统保护。';
|
|
} else {
|
|
$row = $db->prepare('SELECT id, role, is_admin FROM ' . tn('users') . ' WHERE id = ? AND role IN (\'admin\',\'cs\')')->execute([$id])->fetch();
|
|
if (!$row) {
|
|
$err = '账号不存在。';
|
|
} elseif ((int) $row['is_admin'] === 1) {
|
|
// 管理员:确保至少保留一名管理员(含终极管理员)
|
|
$cnt = $db->query('SELECT COUNT(*) FROM ' . tn('users') . ' WHERE role = \'admin\' AND status = 1')->fetchColumn();
|
|
if ((int) $cnt <= 1) {
|
|
$err = '至少要保留一名管理员,不能继续删除。';
|
|
} else {
|
|
$db->prepare('DELETE FROM ' . tn('users') . ' WHERE id = ?')->execute([$id]);
|
|
$msg = '管理员已删除。';
|
|
}
|
|
} else {
|
|
$db->prepare('DELETE FROM ' . tn('users') . ' WHERE id = ?')->execute([$id]);
|
|
$msg = '客服已删除。';
|
|
}
|
|
}
|
|
}
|
|
|
|
// ─── 添加 ──
|
|
if (isset($_POST['add']) && $isAdmin) {
|
|
verifyCsrf();
|
|
$u = trim($_POST['username'] ?? '');
|
|
$em = trim($_POST['email'] ?? '');
|
|
$pw = $_POST['password'] ?? '';
|
|
$role = trim($_POST['role'] ?? 'admin');
|
|
$role = in_array($role, ['admin', 'cs'], true) ? $role : 'admin';
|
|
if (strlen($u) < 3) $err = '账号至少 3 个字符。';
|
|
elseif (!filter_var($em, FILTER_VALIDATE_EMAIL)) $err = '请填写有效的邮箱。';
|
|
elseif (strlen($pw) < 6) $err = '密码至少 6 位。';
|
|
else {
|
|
$chk = $db->prepare('SELECT id FROM ' . tn('users') . ' WHERE username = ?');
|
|
$chk->execute([$u]);
|
|
if ($chk->fetch()) {
|
|
$err = '该用户名已存在。';
|
|
} else {
|
|
$hash = password_hash($pw, PASSWORD_DEFAULT);
|
|
$code = genInviteCode();
|
|
$isAdminFlag = $role === 'admin' ? 1 : 0;
|
|
$db->prepare('INSERT INTO ' . tn('users') . ' (username,password,email,invite_code,is_admin,role,created_at) VALUES (?,?,?,?,?,?,NOW())')
|
|
->execute([$u, $hash, $em, $code, $isAdminFlag, $role]);
|
|
$msg = ($role === 'admin' ? '管理员' : '客服') . '已添加。';
|
|
}
|
|
}
|
|
}
|
|
|
|
$list = $db->query('SELECT id, username, email, status, role, created_at FROM ' . tn('users') . ' WHERE role IN (\'admin\',\'cs\') ORDER BY role DESC, id ASC')->fetchAll();
|
|
|
|
adminHeader('管理员', 'admins');
|
|
?>
|
|
<h1 class="page-title"><i class="fas fa-user-shield"></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; ?>
|
|
|
|
<div class="panel">
|
|
<h3>添加账号(管理员 / 客服)</h3>
|
|
<?php if ($isAdmin): ?>
|
|
<p class="muted">管理员拥有全部后台权限;客服可查看所有页面但仅能处理工单相关操作。</p>
|
|
<form method="post" action="" class="grid-form" style="max-width:680px;">
|
|
<?= csrfField() ?>
|
|
<label>账号 *<input type="text" name="username" placeholder="至少 3 个字符" required></label>
|
|
<label>邮箱 *<input type="email" name="email" required></label>
|
|
<label>角色
|
|
<select name="role">
|
|
<option value="admin">管理员(全部权限)</option>
|
|
<option value="cs">客服(查看 + 工单操作)</option>
|
|
</select>
|
|
</label>
|
|
<label class="span2">密码 *<input type="password" name="password" placeholder="至少 6 位密码" required></label>
|
|
<div class="form-actions span2"><button type="submit" name="add" class="btn btn-primary"><i class="fas fa-user-plus"></i> 添加账号</button></div>
|
|
</form>
|
|
<?php else: ?>
|
|
<p class="muted">客服账号无法添加新管理员,如需操作请联系管理员。</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<h3>账号列表(共 <?= count($list) ?> 名)</h3>
|
|
<?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><th>操作</th></tr></thead>
|
|
<tbody>
|
|
<?php foreach ($list as $a): ?>
|
|
<?php
|
|
$isMe = (int)$a['id'] === (int)$me['id'];
|
|
$isSuper = (int)$a['id'] === 1;
|
|
$isAdm = ($a['role'] === 'admin');
|
|
?>
|
|
<tr <?= $isSuper ? 'style="background:color-mix(in srgb,var(--primary) 6%,transparent)"' : '' ?>>
|
|
<td><?= (int) $a['id'] ?><?= $isSuper ? ' <sup style="color:var(--primary);font-size:.72rem">超级</sup>' : '' ?></td>
|
|
<td><?= h($a['username']) ?><?= $isMe ? ' <span class="badge-on">我</span>' : '' ?></td>
|
|
<td><?= h($a['email']) ?></td>
|
|
<td>
|
|
<?php if ($isAdmin && !$isMe && !$isSuper): ?>
|
|
<form method="post" action="" style="display:inline" onsubmit="return confirmRoleChange(<?= (int) $a['id'] ?>, '<?= h($a['username']) ?>');">
|
|
<?= csrfField() ?>
|
|
<input type="hidden" name="edit_role" value="<?= (int) $a['id'] ?>">
|
|
<select name="new_role" onchange="this.form.submit()" style="padding:2px 6px;border:1px solid var(--outline);border-radius:6px;font-size:.82rem;cursor:pointer;background:transparent;color:inherit">
|
|
<option value="admin" <?php if ($isAdm): ?>selected<?php endif; ?>>管理员</option>
|
|
<option value="cs" <?php if (!$isAdm): ?>selected<?php endif; ?>>客服</option>
|
|
</select>
|
|
</form>
|
|
<?php else: ?>
|
|
<?php if ($isAdm): ?>
|
|
<span class="badge-on">管理员</span>
|
|
<?php else: ?>
|
|
<span class="badge-on" style="background:var(--primary-container);color:var(--on-primary-container)">客服</span>
|
|
<?php endif; ?>
|
|
<?php if ($isSuper): ?><span class="muted" style="font-size:.75rem;margin-left:4px">(受保护)</span><?php endif; ?>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= (int) $a['status'] === 1 ? '<span class="badge-on">正常</span>' : '<span class="badge-off">封禁</span>' ?></td>
|
|
<td><?= date('Y-m-d', strtotime($a['created_at'])) ?></td>
|
|
<td class="row-actions">
|
|
<?php if ($isMe): ?>
|
|
<span class="muted">当前账号</span>
|
|
<?php elseif ($isAdmin): ?>
|
|
<?php if ($isSuper): ?>
|
|
<span class="muted" title="终极管理员受系统保护,不可删除"><i class="fas fa-shield-halved" style="color:var(--primary)"></i> 受保护</span>
|
|
<?php else: ?>
|
|
<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>
|
|
<?php endif; ?>
|
|
<?php else: ?>
|
|
<span class="muted">—</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php if ($isAdmin): ?>
|
|
<p class="muted" style="margin-top:10px;font-size:.82rem">
|
|
<i class="fas fa-info-circle"></i> 终极管理员(ID=1)受系统保护,不可被删除或降级。其他管理员可由同级管理员删除或改为客服。
|
|
</p>
|
|
<?php endif; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
<script>
|
|
function confirmRoleChange(id, name) {
|
|
var sel = event.target.form.elements.new_role;
|
|
var roleLabel = sel.options[sel.selectedIndex].text;
|
|
return confirm('确定将 ' + name + ' 的角色改为「' + roleLabel + '」?');
|
|
}
|
|
</script>
|
|
<?php adminFooter(); ?>
|