/** * 用户控制器 * @file userController.js * @description 处理用户相关的请求 */ const { User, Role, Account } = require('../models'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const { validationResult } = require('express-validator'); /** * 用户注册 * @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: '服务器内部错误' }); } };