You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
7.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 用户数据模型
*
* 功能:封装所有与用户表相关的数据库操作
*
* 说明Model层负责与数据库交互不包含业务逻辑
*/
const { pool } = require('../config/database');
/**
* 用户模型类
*/
class User {
/**
* 根据ID查找用户
* @param {number} id - 用户ID
* @returns {Promise<object|null>} 用户对象或null
*/
static async findById(id) {
try {
const [rows] = await pool.query(
'SELECT * FROM users WHERE id = ?',
[id]
);
return rows[0] || null;
} catch (error) {
throw new Error('查询用户失败: ' + error.message);
}
}
/**
* 根据用户名查找用户
* @param {string} username - 用户名
* @returns {Promise<object|null>} 用户对象或null
*/
static async findByUsername(username) {
try {
const [rows] = await pool.query(
'SELECT * FROM users WHERE username = ?',
[username]
);
return rows[0] || null;
} catch (error) {
throw new Error('查询用户失败: ' + error.message);
}
}
/**
* 根据邮箱查找用户
* @param {string} email - 邮箱
* @returns {Promise<object|null>} 用户对象或null
*/
static async findByEmail(email) {
try {
const [rows] = await pool.query(
'SELECT * FROM users WHERE email = ?',
[email]
);
return rows[0] || null;
} catch (error) {
throw new Error('查询用户失败: ' + error.message);
}
}
/**
* 创建新用户
* @param {object} userData - 用户数据
* @returns {Promise<object>} 创建的用户信息
*/
static async create(userData) {
try {
const { username, password, real_name, phone, email, role = 'customer' } = userData;
const [result] = await pool.query(
`INSERT INTO users (username, password, real_name, phone, email, role)
VALUES (?, ?, ?, ?, ?, ?)`,
[username, password, real_name, phone, email, role]
);
// 返回新创建的用户(不包含密码)
return await this.findByIdWithoutPassword(result.insertId);
} catch (error) {
// 处理唯一性约束错误
if (error.code === 'ER_DUP_ENTRY') {
throw new Error('用户名或邮箱已存在');
}
throw new Error('创建用户失败: ' + error.message);
}
}
/**
* 更新用户信息
* @param {number} id - 用户ID
* @param {object} userData - 要更新的数据
* @returns {Promise<object>} 更新后的用户信息
*/
static async update(id, userData) {
try {
const { real_name, phone, email, avatar } = userData;
// 构建动态更新语句
const updates = [];
const values = [];
if (real_name !== undefined) {
updates.push('real_name = ?');
values.push(real_name);
}
if (phone !== undefined) {
updates.push('phone = ?');
values.push(phone);
}
if (email !== undefined) {
updates.push('email = ?');
values.push(email);
}
if (avatar !== undefined) {
updates.push('avatar = ?');
values.push(avatar);
}
if (updates.length === 0) {
throw new Error('没有要更新的数据');
}
values.push(id); // 添加WHERE条件的参数
await pool.query(
`UPDATE users SET ${updates.join(', ')} WHERE id = ?`,
values
);
return await this.findByIdWithoutPassword(id);
} catch (error) {
throw new Error('更新用户失败: ' + error.message);
}
}
/**
* 更新密码
* @param {number} id - 用户ID
* @param {string} newPassword - 新密码(已加密)
* @returns {Promise<boolean>} 是否成功
*/
static async updatePassword(id, newPassword) {
try {
await pool.query(
'UPDATE users SET password = ? WHERE id = ?',
[newPassword, id]
);
return true;
} catch (error) {
throw new Error('更新密码失败: ' + error.message);
}
}
/**
* 删除用户
* @param {number} id - 用户ID
* @returns {Promise<boolean>} 是否成功
*/
static async delete(id) {
try {
await pool.query('DELETE FROM users WHERE id = ?', [id]);
return true;
} catch (error) {
throw new Error('删除用户失败: ' + error.message);
}
}
/**
* 获取用户列表(分页)
* @param {object} options - 查询选项
* @returns {Promise<object>} 用户列表和总数
*/
static async findAll(options = {}) {
try {
const { page = 1, pageSize = 10, role, status } = options;
const offset = (page - 1) * pageSize;
// 构建WHERE条件
const conditions = [];
const params = [];
if (role) {
conditions.push('role = ?');
params.push(role);
}
if (status !== undefined) {
conditions.push('status = ?');
params.push(status);
}
const whereClause = conditions.length > 0
? 'WHERE ' + conditions.join(' AND ')
: '';
// 查询总数
const [countResult] = await pool.query(
`SELECT COUNT(*) as total FROM users ${whereClause}`,
params
);
const total = countResult[0].total;
// 查询列表(排除密码)
const [rows] = await pool.query(
`SELECT id, username, real_name, phone, email, role, avatar, status, created_at, updated_at
FROM users ${whereClause}
ORDER BY created_at DESC
LIMIT ? OFFSET ?`,
[...params, pageSize, offset]
);
return {
list: rows,
total,
page: parseInt(page),
pageSize: parseInt(pageSize)
};
} catch (error) {
throw new Error('查询用户列表失败: ' + error.message);
}
}
/**
* 查询用户但不返回密码
* @param {number} id - 用户ID
* @returns {Promise<object|null>} 用户对象(不含密码)
*/
static async findByIdWithoutPassword(id) {
try {
const [rows] = await pool.query(
`SELECT id, username, real_name, phone, email, role, avatar, status, created_at, updated_at
FROM users WHERE id = ?`,
[id]
);
return rows[0] || null;
} catch (error) {
throw new Error('查询用户失败: ' + error.message);
}
}
/**
* 更新用户状态
* @param {number} id - 用户ID
* @param {number} status - 状态值1启用/0禁用
* @returns {Promise<boolean>} 是否成功
*/
static async updateStatus(id, status) {
try {
await pool.query(
'UPDATE users SET status = ? WHERE id = ?',
[status, id]
);
return true;
} catch (error) {
throw new Error('更新用户状态失败: ' + error.message);
}
}
/**
* 检查用户名是否已存在
* @param {string} username - 用户名
* @param {number} excludeId - 排除的用户ID用于更新时检查
* @returns {Promise<boolean>} 是否存在
*/
static async isUsernameExists(username, excludeId = null) {
try {
let query = 'SELECT COUNT(*) as count FROM users WHERE username = ?';
const params = [username];
if (excludeId) {
query += ' AND id != ?';
params.push(excludeId);
}
const [rows] = await pool.query(query, params);
return rows[0].count > 0;
} catch (error) {
throw new Error('检查用户名失败: ' + error.message);
}
}
/**
* 检查邮箱是否已存在
* @param {string} email - 邮箱
* @param {number} excludeId - 排除的用户ID
* @returns {Promise<boolean>} 是否存在
*/
static async isEmailExists(email, excludeId = null) {
try {
let query = 'SELECT COUNT(*) as count FROM users WHERE email = ?';
const params = [email];
if (excludeId) {
query += ' AND id != ?';
params.push(excludeId);
}
const [rows] = await pool.query(query, params);
return rows[0].count > 0;
} catch (error) {
throw new Error('检查邮箱失败: ' + error.message);
}
}
}
module.exports = User;