/** * 用户控制器 * @file userController.js * @description 处理用户相关的请求 */ const { User, Role, Account } = require('../models'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const { validationResult } = require('express-validator'); const { Op } = require('sequelize'); /** * 用户注册 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.register = async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, message: '输入数据验证失败', errors: errors.array() }); } const { username, email, password, phone, real_name, id_card } = req.body; // 检查用户名是否已存在 const existingUser = await User.findOne({ where: { username } }); if (existingUser) { return res.status(400).json({ success: false, message: '用户名已存在' }); } // 检查邮箱是否已存在 const existingEmail = await User.findOne({ where: { email } }); if (existingEmail) { return res.status(400).json({ success: false, message: '邮箱已被注册' }); } // 检查身份证是否已存在 const existingIdCard = await User.findOne({ where: { id_card } }); if (existingIdCard) { return res.status(400).json({ success: false, message: '身份证号已被注册' }); } // 创建新用户 const user = await User.create({ username, email, password, phone, real_name, id_card, role_id: 2 // 默认为普通用户 }); // 生成JWT令牌 const token = jwt.sign( { id: user.id, username: user.username }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN || '24h' } ); res.status(201).json({ success: true, message: '注册成功', data: { user: user.getSafeInfo(), token } }); } catch (error) { console.error('用户注册错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 用户登录 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.login = async (req, res) => { try { const { username, password } = req.body; // 查找用户 const user = await User.findOne({ where: { username }, include: [{ model: Role, as: 'role' }] }); if (!user) { return res.status(401).json({ success: false, message: '用户名或密码错误' }); } // 检查账户状态 if (user.status !== 'active') { return res.status(401).json({ success: false, message: '账户已被禁用' }); } // 检查账户是否被锁定 if (user.locked_until && user.locked_until > new Date()) { return res.status(401).json({ success: false, message: '账户已被锁定,请稍后再试' }); } // 验证密码 const isValidPassword = await user.validPassword(password); if (!isValidPassword) { // 增加登录失败次数 user.login_attempts += 1; // 如果失败次数达到5次,锁定账户1小时 if (user.login_attempts >= 5) { user.locked_until = new Date(Date.now() + 60 * 60 * 1000); // 1小时后解锁 } await user.save(); return res.status(401).json({ success: false, message: '用户名或密码错误' }); } // 登录成功,重置登录失败次数 user.login_attempts = 0; user.locked_until = null; user.last_login = new Date(); await user.save(); // 生成JWT令牌 const token = jwt.sign( { id: user.id, username: user.username }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN || '24h' } ); res.json({ success: true, message: '登录成功', data: { user: user.getSafeInfo(), token } }); } catch (error) { console.error('用户登录错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 获取用户信息 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.getProfile = async (req, res) => { try { const user = await User.findByPk(req.user.id, { include: [{ model: Role, as: 'role' }] }); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } res.json({ success: true, data: user.getSafeInfo() }); } catch (error) { console.error('获取用户信息错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 更新用户信息 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.updateProfile = async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, message: '输入数据验证失败', errors: errors.array() }); } const { phone, real_name, avatar } = req.body; const user = await User.findByPk(req.user.id); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } // 更新用户信息 await user.update({ phone: phone || user.phone, real_name: real_name || user.real_name, avatar: avatar || user.avatar }); res.json({ success: true, message: '用户信息更新成功', data: user.getSafeInfo() }); } catch (error) { console.error('更新用户信息错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 修改密码 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.changePassword = async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, message: '输入数据验证失败', errors: errors.array() }); } const { old_password, new_password } = req.body; const user = await User.findByPk(req.user.id); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } // 验证旧密码 const isValidPassword = await user.validPassword(old_password); if (!isValidPassword) { return res.status(400).json({ success: false, message: '原密码错误' }); } // 更新密码 user.password = new_password; await user.save(); res.json({ success: true, message: '密码修改成功' }); } catch (error) { console.error('修改密码错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 获取用户列表(管理员) * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.getUsers = async (req, res) => { try { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 10; const offset = (page - 1) * limit; const search = req.query.search || ''; const whereClause = {}; if (search) { whereClause[Op.or] = [ { username: { [Op.like]: `%${search}%` } }, { email: { [Op.like]: `%${search}%` } }, { real_name: { [Op.like]: `%${search}%` } } ]; } const { count, rows } = await User.findAndCountAll({ where: whereClause, include: [{ model: Role, as: 'role' }], limit, offset, order: [['created_at', 'DESC']] }); res.json({ success: true, data: { users: rows.map(user => user.getSafeInfo()), pagination: { page, limit, total: count, pages: Math.ceil(count / limit) } } }); } catch (error) { console.error('获取用户列表错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 更新用户状态(管理员) * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.updateUserStatus = async (req, res) => { try { const { userId } = req.params; const { status } = req.body; const user = await User.findByPk(userId); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } await user.update({ status }); res.json({ success: true, message: '用户状态更新成功', data: user.getSafeInfo() }); } catch (error) { console.error('更新用户状态错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 获取用户账户列表 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.getUserAccounts = async (req, res) => { try { const userId = req.params.userId || req.user.id; // 检查权限:用户只能查看自己的账户,管理员可以查看所有账户 if (userId !== req.user.id.toString() && req.user.role.name !== 'admin') { return res.status(403).json({ success: false, message: '无权访问该用户的账户信息' }); } const accounts = await Account.findAll({ where: { user_id: userId }, order: [['created_at', 'DESC']] }); res.json({ success: true, data: accounts.map(account => ({ ...account.getSafeInfo(), balance_formatted: account.getBalanceFormatted(), available_balance_formatted: account.getAvailableBalanceFormatted(), frozen_amount_formatted: account.getFrozenAmountFormatted() })) }); } catch (error) { console.error('获取用户账户列表错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 创建用户(管理员) * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.createUser = async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, message: '输入数据验证失败', errors: errors.array() }); } const { username, email, password, phone, real_name, id_card, role_id } = req.body; // 检查用户名是否已存在 const existingUser = await User.findOne({ where: { username } }); if (existingUser) { return res.status(400).json({ success: false, message: '用户名已存在' }); } // 检查邮箱是否已存在 const existingEmail = await User.findOne({ where: { email } }); if (existingEmail) { return res.status(400).json({ success: false, message: '邮箱已被注册' }); } // 创建新用户 const user = await User.create({ username, email, password, phone, real_name, id_card, role_id: role_id || 2 // 默认为普通用户 }); // 获取用户信息(包含角色) const userWithRole = await User.findByPk(user.id, { include: [{ model: Role, as: 'role' }] }); res.status(201).json({ success: true, message: '用户创建成功', data: userWithRole.getSafeInfo() }); } catch (error) { console.error('创建用户错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 更新用户信息(管理员) * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.updateUser = async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, message: '输入数据验证失败', errors: errors.array() }); } const { userId } = req.params; const { username, email, phone, real_name, id_card, role_id, status } = req.body; const user = await User.findByPk(userId); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } // 检查用户名是否被其他用户使用 if (username && username !== user.username) { const existingUser = await User.findOne({ where: { username, id: { [Op.ne]: userId } } }); if (existingUser) { return res.status(400).json({ success: false, message: '用户名已被其他用户使用' }); } } // 检查邮箱是否被其他用户使用 if (email && email !== user.email) { const existingEmail = await User.findOne({ where: { email, id: { [Op.ne]: userId } } }); if (existingEmail) { return res.status(400).json({ success: false, message: '邮箱已被其他用户使用' }); } } // 更新用户信息 await user.update({ username: username || user.username, email: email || user.email, phone: phone || user.phone, real_name: real_name || user.real_name, id_card: id_card || user.id_card, role_id: role_id || user.role_id, status: status || user.status }); // 获取更新后的用户信息(包含角色) const updatedUser = await User.findByPk(userId, { include: [{ model: Role, as: 'role' }] }); res.json({ success: true, message: '用户信息更新成功', data: updatedUser.getSafeInfo() }); } catch (error) { console.error('更新用户信息错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 删除用户(管理员) * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.deleteUser = async (req, res) => { try { const { userId } = req.params; const user = await User.findByPk(userId); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } // 检查是否是当前用户 if (userId === req.user.userId.toString()) { return res.status(400).json({ success: false, message: '不能删除自己的账户' }); } // 软删除用户(更新状态为inactive) await user.update({ status: 'inactive' }); res.json({ success: true, message: '用户删除成功' }); } catch (error) { console.error('删除用户错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 重置用户密码(管理员) * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.resetPassword = async (req, res) => { try { const { userId } = req.params; const { newPassword } = req.body; const user = await User.findByPk(userId); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } // 更新密码 user.password = newPassword; await user.save(); res.json({ success: true, message: '密码重置成功' }); } catch (error) { console.error('重置密码错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 获取用户详情 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ exports.getUserById = async (req, res) => { try { const { userId } = req.params; const user = await User.findByPk(userId, { include: [{ model: Role, as: 'role' }] }); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } res.json({ success: true, message: '获取用户详情成功', data: user.getSafeInfo() }); } catch (error) { console.error('获取用户详情错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } };