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.
 
 
 
 
 
 

414 lines
13 KiB

import UserModel from "db/models/UserModel.js"
import { hashPassword, comparePassword } from "utils/bcrypt.js"
import CommonError from "utils/error/CommonError.js"
import { JWT_SECRET } from "@/middlewares/Auth/auth.js"
import jwt from "@/middlewares/Auth/jwt.js"
class UserService {
// 根据ID获取用户
async getUserById(id) {
try {
if (!id) {
throw new CommonError("用户ID不能为空")
}
const user = await UserModel.findById(id)
if (!user) {
throw new CommonError("用户不存在")
}
// 返回脱敏信息
const { password, ...userInfo } = user
return userInfo
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`获取用户失败: ${error.message}`)
}
}
// 获取所有用户
async getAllUsers() {
try {
const users = await UserModel.findAll()
// 返回脱敏信息
return users.map(user => {
const { password, ...userInfo } = user
return userInfo
})
} catch (error) {
throw new CommonError(`获取用户列表失败: ${error.message}`)
}
}
// 创建新用户
async createUser(data) {
try {
if (!data.username || !data.password) {
throw new CommonError("用户名和密码为必填字段")
}
// 检查用户名是否已存在
const existUser = await UserModel.findByUsername(data.username)
if (existUser) {
throw new CommonError(`用户名${data.username}已存在`)
}
// 检查邮箱是否已存在
if (data.email) {
const existEmail = await UserModel.findByEmail(data.email)
if (existEmail) {
throw new CommonError(`邮箱${data.email}已被使用`)
}
}
// 密码加密
const hashedPassword = await hashPassword(data.password)
const user = await UserModel.create({
...data,
password: hashedPassword
})
// 返回脱敏信息
const { password, ...userInfo } = Array.isArray(user) ? user[0] : user
return userInfo
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`创建用户失败: ${error.message}`)
}
}
// 更新用户
async updateUser(id, data) {
try {
if (!id) {
throw new CommonError("用户ID不能为空")
}
const user = await UserModel.findById(id)
if (!user) {
throw new CommonError("用户不存在")
}
// 如果要更新用户名,检查是否重复
if (data.username && data.username !== user.username) {
const existUser = await UserModel.findByUsername(data.username)
if (existUser) {
throw new CommonError(`用户名${data.username}已存在`)
}
}
// 如果要更新邮箱,检查是否重复
if (data.email && data.email !== user.email) {
const existEmail = await UserModel.findByEmail(data.email)
if (existEmail) {
throw new CommonError(`邮箱${data.email}已被使用`)
}
}
// 如果要更新密码,需要加密
if (data.password) {
data.password = await hashPassword(data.password)
}
const updatedUser = await UserModel.update(id, data)
// 返回脱敏信息
const { password, ...userInfo } = Array.isArray(updatedUser) ? updatedUser[0] : updatedUser
return userInfo
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`更新用户失败: ${error.message}`)
}
}
// 删除用户
async deleteUser(id) {
try {
if (!id) {
throw new CommonError("用户ID不能为空")
}
const user = await UserModel.findById(id)
if (!user) {
throw new CommonError("用户不存在")
}
return await UserModel.delete(id)
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`删除用户失败: ${error.message}`)
}
}
// 注册新用户
async register(data) {
try {
if (!data.username || !data.password) {
throw new CommonError("用户名和密码不能为空")
}
// 检查用户名是否已存在
const existUser = await UserModel.findByUsername(data.username)
if (existUser) {
throw new CommonError(`用户名${data.username}已存在`)
}
// 检查邮箱是否已存在
if (data.email) {
const existEmail = await UserModel.findByEmail(data.email)
if (existEmail) {
throw new CommonError(`邮箱${data.email}已被使用`)
}
}
// 密码加密
const hashed = await hashPassword(data.password)
const user = await UserModel.create({ ...data, password: hashed })
// 返回脱敏信息
const { password, ...userInfo } = Array.isArray(user) ? user[0] : user
return userInfo
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`注册失败: ${error.message}`)
}
}
// 登录
async login({ username, email, password }) {
try {
if (!password) {
throw new CommonError("密码不能为空")
}
if (!username && !email) {
throw new CommonError("用户名或邮箱不能为空")
}
let user
if (username) {
user = await UserModel.findByUsername(username)
} else if (email) {
user = await UserModel.findByEmail(email)
}
if (!user) {
throw new CommonError("用户不存在")
}
// 校验密码
const ok = await comparePassword(password, user.password)
if (!ok) {
throw new CommonError("密码错误")
}
// 生成token
const token = jwt.sign(
{ id: user.id, username: user.username },
JWT_SECRET,
{ expiresIn: "2h" }
)
// 返回token和用户信息
const { password: pwd, ...userInfo } = user
return { token, user: userInfo }
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`登录失败: ${error.message}`)
}
}
// 根据用户名查找用户
async getUserByUsername(username) {
try {
if (!username) {
throw new CommonError("用户名不能为空")
}
const user = await UserModel.findByUsername(username)
if (!user) {
throw new CommonError("用户不存在")
}
// 返回脱敏信息
const { password, ...userInfo } = user
return userInfo
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`获取用户失败: ${error.message}`)
}
}
// 根据邮箱查找用户
async getUserByEmail(email) {
try {
if (!email) {
throw new CommonError("邮箱不能为空")
}
const user = await UserModel.findByEmail(email)
if (!user) {
throw new CommonError("用户不存在")
}
// 返回脱敏信息
const { password, ...userInfo } = user
return userInfo
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`获取用户失败: ${error.message}`)
}
}
// 修改密码
async changePassword(userId, oldPassword, newPassword) {
try {
if (!userId || !oldPassword || !newPassword) {
throw new CommonError("用户ID、旧密码和新密码不能为空")
}
const user = await UserModel.findById(userId)
if (!user) {
throw new CommonError("用户不存在")
}
// 验证旧密码
const isOldPasswordCorrect = await comparePassword(oldPassword, user.password)
if (!isOldPasswordCorrect) {
throw new CommonError("旧密码错误")
}
// 加密新密码
const hashedNewPassword = await hashPassword(newPassword)
// 更新密码
await UserModel.update(userId, { password: hashedNewPassword })
return { message: "密码修改成功" }
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`修改密码失败: ${error.message}`)
}
}
// 重置密码
async resetPassword(email, newPassword) {
try {
if (!email || !newPassword) {
throw new CommonError("邮箱和新密码不能为空")
}
const user = await UserModel.findByEmail(email)
if (!user) {
throw new CommonError("用户不存在")
}
// 加密新密码
const hashedPassword = await hashPassword(newPassword)
// 更新密码
await UserModel.update(user.id, { password: hashedPassword })
return { message: "密码重置成功" }
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`重置密码失败: ${error.message}`)
}
}
// 获取用户统计信息
async getUserStats() {
try {
const users = await UserModel.findAll()
const stats = {
total: users.length,
active: users.filter(user => user.status === 'active').length,
inactive: users.filter(user => user.status === 'inactive').length,
byRole: {},
byDate: {}
}
// 按角色分组统计
users.forEach(user => {
const role = user.role || 'user'
stats.byRole[role] = (stats.byRole[role] || 0) + 1
})
// 按创建时间分组统计
users.forEach(user => {
const date = new Date(user.created_at).toISOString().split('T')[0]
stats.byDate[date] = (stats.byDate[date] || 0) + 1
})
return stats
} catch (error) {
throw new CommonError(`获取用户统计失败: ${error.message}`)
}
}
// 搜索用户
async searchUsers(keyword) {
try {
if (!keyword || keyword.trim() === '') {
return await this.getAllUsers()
}
const users = await UserModel.findAll()
const searchTerm = keyword.toLowerCase().trim()
const filteredUsers = users.filter(user => {
return (
user.username?.toLowerCase().includes(searchTerm) ||
user.email?.toLowerCase().includes(searchTerm) ||
user.name?.toLowerCase().includes(searchTerm)
)
})
// 返回脱敏信息
return filteredUsers.map(user => {
const { password, ...userInfo } = user
return userInfo
})
} catch (error) {
throw new CommonError(`搜索用户失败: ${error.message}`)
}
}
// 批量删除用户
async deleteUsers(userIds) {
try {
if (!Array.isArray(userIds) || userIds.length === 0) {
throw new CommonError("用户ID列表不能为空")
}
const results = []
const errors = []
for (const id of userIds) {
try {
await this.deleteUser(id)
results.push(id)
} catch (error) {
errors.push({
id,
error: error.message
})
}
}
return {
success: results,
errors,
total: userIds.length,
successCount: results.length,
errorCount: errors.length
}
} catch (error) {
if (error instanceof CommonError) throw error
throw new CommonError(`批量删除用户失败: ${error.message}`)
}
}
}
export default UserService