Files
2026-08-14 10:55:06 +08:00

200 lines
9.3 KiB
PHP
Raw Permalink 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['toggle'])) {
verifyCsrf();
$id = (int) ($_POST['toggle'] ?? 0);
$stmt = $db->prepare('SELECT id, is_admin, status FROM ' . tn('users') . ' WHERE id = ?');
$stmt->execute([$id]);
$row = $stmt->fetch();
if (!$row) {
$err = '用户不存在';
} elseif ((int) $row['is_admin'] === 1) {
$err = '不能对管理员执行该操作';
} else {
$next = ((int) $row['status'] === 1) ? 0 : 1;
$db->prepare('UPDATE ' . tn('users') . ' SET status = ? WHERE id = ?')->execute([$next, $id]);
$msg = $next === 0 ? '该用户已被封禁,无法再登录。' : '已解除封禁。';
}
}
// 删除
if (isset($_POST['delete'])) {
verifyCsrf();
$id = (int) ($_POST['delete'] ?? 0);
$stmt = $db->prepare('SELECT id, is_admin FROM ' . tn('users') . ' WHERE id = ?');
$stmt->execute([$id]);
$row = $stmt->fetch();
if (!$row) {
$err = '用户不存在';
} elseif ((int) $row['is_admin'] === 1) {
$err = '不能删除管理员账户';
} else {
$db->prepare('DELETE FROM ' . tn('users') . ' WHERE id = ? AND is_admin = 0')->execute([$id]);
$msg = '用户已删除';
}
}
// 添加
if (isset($_POST['add'])) {
verifyCsrf();
$u = trim($_POST['username'] ?? '');
$em = trim($_POST['email'] ?? '');
$pw = $_POST['password'] ?? '';
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();
$db->prepare('INSERT INTO ' . tn('users') . ' (username,password,email,invite_code,created_at) VALUES (?,?,?,?,NOW())')
->execute([$u, $hash, $em, $code]);
$msg = '用户已添加';
}
}
}
// 手动调整积分
if (isset($_POST['adjust'])) {
verifyCsrf();
$target = trim($_POST['target'] ?? '');
$amount = (int) ($_POST['amount'] ?? 0);
$remark = trim($_POST['remark'] ?? '');
if ($target === '') $err = '请填写用户 ID 或用户名';
elseif ($amount === 0) $err = '积分变动不能为 0';
elseif ($remark === '') $err = '请填写调整备注(便于留痕)';
else {
if (is_numeric($target)) {
$stmt = $db->prepare('SELECT id, is_admin FROM ' . tn('users') . ' WHERE id = ?');
$stmt->execute([(int) $target]);
} else {
$stmt = $db->prepare('SELECT id, is_admin FROM ' . tn('users') . ' WHERE username = ?');
$stmt->execute([$target]);
}
$row = $stmt->fetch();
if (!$row) {
$err = '未找到该用户';
} else {
$res = addPoints((int) $row['id'], 'manual', $amount, '后台手动调整:' . $remark);
if ($res['ok']) {
$msg = '已为用户 #' . (int) $row['id'] . ' ' . ($amount > 0 ? '增加' : '扣减') . ' ' . abs($amount) . ' 积分,当前余额 ' . $res['balance'] . ' 分。';
} else {
$err = '调整失败:' . $res['error'];
}
}
}
}
// 切换邮箱验证状态
if (isset($_POST['toggle_verify'])) {
verifyCsrf();
$id = (int) ($_POST['toggle_verify'] ?? 0);
$stmt = $db->prepare('SELECT id, verified FROM ' . tn('users') . ' WHERE id = ?');
$stmt->execute([$id]);
$row = $stmt->fetch();
if (!$row) {
$err = '用户不存在';
} else {
$next = (int) $row['verified'] === 1 ? 0 : 1;
$db->prepare('UPDATE ' . tn('users') . ' SET verified = ? WHERE id = ?')->execute([$next, $id]);
$msg = $next === 1 ? '已标记该用户邮箱为已验证。' : '已将该用户邮箱设为未验证。';
}
}
$list = $db->query('SELECT id, username, email, status, points, verified, created_at FROM ' . tn('users') . ' WHERE is_admin = 0 ORDER BY created_at DESC')->fetchAll();
$orderCnt = $db->query('SELECT user_id, COUNT(*) c FROM ' . tn('orders') . ' GROUP BY user_id')->fetchAll(PDO::FETCH_KEY_PAIR);
adminHeader('用户管理', 'users');
?>
<h1 class="page-title"><i class="fas fa-users"></i> 用户管理(共 <?= count($list) ?> 人)</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>
<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 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>
</div>
<div class="panel">
<h3>手动调整积分</h3>
<form method="post" action="" class="grid-form" style="max-width:720px;">
<?= csrfField() ?>
<label>用户 ID 或用户名 *<input type="text" name="target" placeholder="如 12 或 xiaoming" required></label>
<label>积分变动 *<input type="number" name="amount" placeholder="正数=增加,负数=扣减" required></label>
<label class="span2">调整备注 *<input type="text" name="remark" placeholder="如「活动奖励」「误扣退回」等" required></label>
<div class="form-actions span2">
<button type="submit" name="adjust" class="btn btn-primary"><i class="fas fa-coins"></i> 提交调整</button>
</div>
</form>
</div>
<div class="panel">
<h3>用户列表</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><th>注册时间</th><th>操作</th></tr></thead>
<tbody>
<?php foreach ($list as $u): ?>
<tr>
<td><?= (int) $u['id'] ?></td>
<td><?= h($u['username']) ?></td>
<td><?= h($u['email']) ?></td>
<td><?= (int) ($u['points'] ?? 0) ?></td>
<td><?= (int) ($orderCnt[$u['id']] ?? 0) ?></td>
<td>
<?php if ((int) $u['verified'] === 1): ?>
<span class="badge-on">已验证</span>
<?php else: ?>
<span class="badge-off" style="background:var(--warn);color:#000">未验证</span>
<?php endif; ?>
</td>
<td><?= (int) $u['status'] === 1 ? '<span class="badge-on">正常</span>' : '<span class="badge-off">已封禁</span>' ?></td>
<td><?= date('Y-m-d', strtotime($u['created_at'])) ?></td>
<td class="row-actions">
<form method="post" action="" style="display:inline" onsubmit="return confirm('确定<?= (int)$u['status']===1?'封禁':'解封' ?>该用户?');">
<?= csrfField() ?>
<button type="submit" name="toggle" value="<?= (int) $u['id'] ?>" class="mini-btn <?= (int)$u['status']===1?'warn':'ok' ?>"><i class="fas fa-<?= (int)$u['status']===1?'ban':'check' ?>"></i></button>
</form>
<form method="post" action="" style="display:inline" onsubmit="return confirm('确定<?= (int)$u['verified']===1?'取消验证':'标记已验证' ?>');">
<?= csrfField() ?>
<button type="submit" name="toggle_verify" value="<?= (int) $u['id'] ?>" class="mini-btn <?= (int)$u['verified']===1?'warn':'ok' ?>" title="切换邮箱验证状态"><i class="fas fa-<?= (int)$u['verified']===1?'envelope':'envelope-circle-check' ?>"></i></button>
</form>
<form method="post" action="" style="display:inline" onsubmit="return confirm('确定删除该用户?此操作不可恢复。');">
<?= csrfField() ?>
<button type="submit" name="delete" value="<?= (int) $u['id'] ?>" class="mini-btn danger"><i class="fas fa-trash"></i></button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
<?php adminFooter(); ?>