feat(用户管理): 实现用户注册审核功能

添加用户注册审核流程,包括以下变更:
- 用户注册后状态为 pending 待审核
- 管理员可批准或拒绝注册申请
- 待审核用户无法登录系统
- 用户管理页面添加审核操作和状态筛选
- 添加数据库迁移脚本支持 pending 状态
- 更新前后端相关接口和页面逻辑
This commit is contained in:
zhang1106
2026-02-05 15:12:31 +08:00
parent 719812f012
commit ebd4b5faa9
9 changed files with 404 additions and 205 deletions
+44 -20
View File
@@ -58,12 +58,12 @@ router.post('/register', async (req, res) => {
email,
phone,
realName: realName || username,
status: 'active'
status: isFirstUser ? 'active' : 'pending'
});
if (isFirstUser) {
let adminRole = await Role.findOne({ where: { roleCode: 'admin' } });
if (!adminRole) {
adminRole = await Role.create({
roleId: 'role_admin',
@@ -74,37 +74,53 @@ router.post('/register', async (req, res) => {
permissions: []
});
}
await UserRole.create({
UserId: user.userId,
RoleId: adminRole.roleId
});
const token = generateToken(user);
res.status(201).json({
success: true,
message: '注册成功,已为您分配管理员权限',
data: {
user: {
userId: user.userId,
username: user.username,
email: user.email,
realName: user.realName
},
token,
isFirstUser: true
}
});
} else {
const defaultRole = await Role.findOne({ where: { roleCode: 'viewer' } });
if (defaultRole) {
await UserRole.create({
UserId: user.userId,
RoleId: defaultRole.roleId
});
}
res.status(201).json({
success: true,
message: '注册成功,请等待管理员审核',
data: {
user: {
userId: user.userId,
username: user.username,
email: user.email,
realName: user.realName
},
isFirstUser: false,
pendingApproval: true
}
});
}
const token = generateToken(user);
res.status(201).json({
success: true,
message: isFirstUser ? '注册成功,已为您分配管理员权限' : '注册成功',
data: {
user: {
userId: user.userId,
username: user.username,
email: user.email,
realName: user.realName
},
token
}
});
} catch (error) {
console.error('注册错误:', error);
res.status(500).json({
@@ -148,6 +164,14 @@ router.post('/login', async (req, res) => {
});
}
if (user.status === 'pending') {
return res.status(403).json({
success: false,
code: 'PENDING_APPROVAL',
message: '账户待审核,请联系管理员激活'
});
}
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
user.loginCount = (user.loginCount || 0) + 1;
+78
View File
@@ -465,4 +465,82 @@ router.delete('/:userId/avatar', authMiddleware, async (req, res) => {
}
});
router.put('/:userId/approve', authMiddleware, async (req, res) => {
try {
const user = await User.findByPk(req.params.userId);
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
if (user.status !== 'pending') {
return res.status(400).json({
success: false,
message: '该用户不在待审核状态'
});
}
user.status = 'active';
await user.save();
res.json({
success: true,
message: '用户审核通过',
data: {
userId: user.userId,
username: user.username,
status: user.status
}
});
} catch (error) {
console.error('审核用户错误:', error);
res.status(500).json({
success: false,
message: '审核用户失败'
});
}
});
router.put('/:userId/reject', authMiddleware, async (req, res) => {
try {
const user = await User.findByPk(req.params.userId);
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
if (user.status !== 'pending') {
return res.status(400).json({
success: false,
message: '该用户不在待审核状态'
});
}
user.status = 'inactive';
await user.save();
res.json({
success: true,
message: '已拒绝该用户的注册申请',
data: {
userId: user.userId,
username: user.username,
status: user.status
}
});
} catch (error) {
console.error('拒绝用户错误:', error);
res.status(500).json({
success: false,
message: '操作失败'
});
}
});
module.exports = router;