/** * 管理员业务服务 * * 功能描述: * - 管理员登录认证业务逻辑 * - 用户管理业务功能(查询、密码重置、状态管理) * - 系统日志管理功能 * * 职责分离: * - 业务逻辑编排和数据格式化 * - 调用核心服务完成具体操作 * - 异常处理和日志记录 * * 主要方法: * - login() - 管理员登录认证 * - listUsers() - 用户列表查询 * - getUser() - 单个用户查询 * - resetPassword() - 重置用户密码 * - updateUserStatus() - 修改用户状态 * - batchUpdateUserStatus() - 批量修改用户状态 * - getUserStatusStats() - 获取用户状态统计 * - getRuntimeLogs() - 获取运行日志 * * 使用场景: * - 后台管理系统的业务逻辑处理 * - 管理员权限相关的业务操作 * * 最近修改: * - 2026-01-07: 代码规范优化 - 修正文件命名规范,更新作者信息和修改记录 * - 2026-01-08: 注释规范优化 - 补充方法注释,添加@param、@returns、@throws和@example (修改者: moyin) * * @author moyin * @version 1.0.2 * @since 2025-12-19 * @lastModified 2026-01-08 */ import { Inject, Injectable, Logger, NotFoundException, BadRequestException } from '@nestjs/common'; import { AdminCoreService } from '../../core/admin_core/admin_core.service'; import { Users } from '../../core/db/users/users.entity'; import { UsersService } from '../../core/db/users/users.service'; import { UsersMemoryService } from '../../core/db/users/users_memory.service'; import { LogManagementService } from '../../core/utils/logger/log_management.service'; import { UserStatus, getUserStatusDescription } from '../user_mgmt/user_status.enum'; import { UserStatusDto, BatchUserStatusDto } from '../user_mgmt/user_status.dto'; import { getCurrentTimestamp } from './admin_utils'; import { USER_QUERY_LIMITS } from './admin_constants'; import { UserStatusResponseDto, BatchUserStatusResponseDto, UserStatusStatsResponseDto, UserStatusInfoDto, BatchOperationResultDto } from '../user_mgmt/user_status_response.dto'; export interface AdminApiResponse { success: boolean; data?: T; message: string; error_code?: string; } @Injectable() export class AdminService { private readonly logger = new Logger(AdminService.name); constructor( private readonly adminCoreService: AdminCoreService, @Inject('UsersService') private readonly usersService: UsersService | UsersMemoryService, private readonly logManagementService: LogManagementService, ) {} /** * 记录操作日志 * * @param level 日志级别 * @param message 日志消息 * @param context 日志上下文 */ private logOperation(level: 'log' | 'warn' | 'error', message: string, context: Record): void { this.logger[level](message, { ...context, timestamp: getCurrentTimestamp() }); } /** * 获取日志目录绝对路径 * * @returns 日志目录的绝对路径 */ getLogDirAbsolutePath(): string { return this.logManagementService.getLogDirAbsolutePath(); } /** * 管理员登录 * * 功能描述: * 验证管理员身份并生成JWT Token * * 业务逻辑: * 1. 调用核心服务验证登录信息 * 2. 生成JWT Token * 3. 返回登录结果 * * @param identifier 登录标识符(用户名/邮箱/手机号) * @param password 密码 * @returns 登录结果,包含Token和管理员信息 * * @example * ```typescript * const result = await adminService.login('admin', 'password123'); * ``` */ async login(identifier: string, password: string): Promise { try { const result = await this.adminCoreService.login({ identifier, password }); return { success: true, data: result, message: '管理员登录成功' }; } catch (error) { this.logger.error(`管理员登录失败: ${identifier}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '管理员登录失败', error_code: 'ADMIN_LOGIN_FAILED', }; } } /** * 获取用户列表 * * 功能描述: * 分页获取系统中的用户列表 * * 业务逻辑: * 1. 调用用户服务获取用户数据 * 2. 格式化用户信息 * 3. 返回分页结果 * * @param limit 返回数量限制 * @param offset 偏移量 * @returns 用户列表和分页信息 * * @example * ```typescript * const result = await adminService.listUsers(20, 0); * ``` */ async listUsers(limit: number, offset: number): Promise> { const users = await this.usersService.findAll(limit, offset); return { success: true, data: { users: users.map((u: Users) => this.formatUser(u)), limit, offset, }, message: '用户列表获取成功', }; } /** * 获取用户详情 * * 功能描述: * 根据用户ID获取指定用户的详细信息 * * 业务逻辑: * 1. 查询用户信息 * 2. 格式化用户数据 * 3. 返回用户详情 * * @param id 用户ID * @returns 用户详细信息 * * @throws NotFoundException 当用户不存在时 * * @example * ```typescript * const result = await adminService.getUser(BigInt(123)); * ``` */ async getUser(id: bigint): Promise> { const user = await this.usersService.findOne(id); return { success: true, data: { user: this.formatUser(user) }, message: '用户信息获取成功', }; } /** * 重置用户密码 * * 功能描述: * 管理员直接为指定用户设置新密码 * * 业务逻辑: * 1. 验证用户是否存在 * 2. 调用核心服务重置密码 * 3. 记录操作日志 * 4. 返回重置结果 * * @param id 用户ID * @param newPassword 新密码 * @returns 重置结果 * * @throws NotFoundException 当用户不存在时 * * @example * ```typescript * const result = await adminService.resetPassword(BigInt(123), 'NewPass1234'); * ``` */ async resetPassword(id: bigint, newPassword: string): Promise { // 确认用户存在 const user = await this.usersService.findOne(id).catch((): null => null); if (!user) { throw new NotFoundException('用户不存在'); } await this.adminCoreService.resetUserPassword(id, newPassword); this.logger.log(`管理员重置密码成功: userId=${id.toString()}`); return { success: true, message: '密码重置成功' }; } /** * 获取运行日志 * * 功能描述: * 获取系统运行日志的尾部内容 * * 业务逻辑: * 1. 调用日志管理服务获取日志 * 2. 返回日志内容和元信息 * * @param lines 返回的日志行数,可选参数 * @returns 日志内容和元信息 * * @example * ```typescript * const result = await adminService.getRuntimeLogs(200); * ``` */ async getRuntimeLogs(lines?: number): Promise> { const result = await this.logManagementService.getRuntimeLogTail({ lines }); return { success: true, data: result, message: '运行日志获取成功', }; } private formatUser(user: Users) { return { id: user.id.toString(), username: user.username, nickname: user.nickname, email: user.email, email_verified: user.email_verified, phone: user.phone, avatar_url: user.avatar_url, role: user.role, status: user.status || UserStatus.ACTIVE, // 兼容旧数据 created_at: user.created_at, updated_at: user.updated_at, }; } /** * 格式化用户状态信息 * * @param user 用户实体 * @returns 格式化的用户状态信息 */ private formatUserStatus(user: Users): UserStatusInfoDto { return { id: user.id.toString(), username: user.username, nickname: user.nickname, status: user.status || UserStatus.ACTIVE, status_description: getUserStatusDescription(user.status || UserStatus.ACTIVE), updated_at: user.updated_at }; } /** * 修改用户状态 * * 功能描述: * 管理员修改指定用户的账户状态,支持激活、锁定、禁用等操作 * * 业务逻辑: * 1. 验证用户是否存在 * 2. 检查状态变更的合法性 * 3. 更新用户状态 * 4. 记录状态变更日志 * * @param userId 用户ID * @param userStatusDto 状态修改数据 * @returns 修改结果 * * @throws NotFoundException 当用户不存在时 * @throws BadRequestException 当状态变更不合法时 */ async updateUserStatus(userId: bigint, userStatusDto: UserStatusDto): Promise { try { this.logOperation('log', '开始修改用户状态', { operation: 'update_user_status', userId: userId.toString(), newStatus: userStatusDto.status, reason: userStatusDto.reason }); // 1. 验证用户是否存在 const user = await this.usersService.findOne(userId); if (!user) { this.logOperation('warn', '修改用户状态失败:用户不存在', { operation: 'update_user_status', userId: userId.toString() }); throw new NotFoundException('用户不存在'); } // 2. 检查状态变更的合法性 if (user.status === userStatusDto.status) { this.logOperation('warn', '修改用户状态失败:状态未发生变化', { operation: 'update_user_status', userId: userId.toString(), currentStatus: user.status, newStatus: userStatusDto.status }); throw new BadRequestException('用户状态未发生变化'); } // 3. 更新用户状态 const updatedUser = await this.usersService.update(userId, { status: userStatusDto.status }); // 4. 记录状态变更日志 this.logOperation('log', '用户状态修改成功', { operation: 'update_user_status', userId: userId.toString(), oldStatus: user.status, newStatus: userStatusDto.status, reason: userStatusDto.reason }); return { success: true, data: { user: this.formatUserStatus(updatedUser), reason: userStatusDto.reason }, message: '用户状态修改成功' }; } catch (error) { this.logOperation('error', '修改用户状态失败', { operation: 'update_user_status', userId: userId.toString(), error: error instanceof Error ? error.message : String(error) }); if (error instanceof NotFoundException || error instanceof BadRequestException) { throw error; } return { success: false, message: '用户状态修改失败', error_code: 'USER_STATUS_UPDATE_FAILED' }; } } /** * 处理单个用户状态修改 * * @param userIdStr 用户ID字符串 * @param newStatus 新状态 * @returns 处理结果 */ private async processSingleUserStatus( userIdStr: string, newStatus: UserStatus ): Promise<{ success: true; user: UserStatusInfoDto } | { success: false; error: string }> { try { const userId = BigInt(userIdStr); // 验证用户是否存在 const user = await this.usersService.findOne(userId); if (!user) { return { success: false, error: '用户不存在' }; } // 检查状态是否需要变更 if (user.status === newStatus) { return { success: false, error: '用户状态未发生变化' }; } // 更新用户状态 const updatedUser = await this.usersService.update(userId, { status: newStatus }); return { success: true, user: this.formatUserStatus(updatedUser) }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : '未知错误' }; } } /** * 批量修改用户状态 * * 功能描述: * 管理员批量修改多个用户的账户状态 * * 业务逻辑: * 1. 验证用户ID列表 * 2. 逐个处理用户状态修改 * 3. 收集成功和失败的结果 * 4. 返回批量操作结果 * * @param batchUserStatusDto 批量状态修改数据 * @returns 批量修改结果 */ async batchUpdateUserStatus(batchUserStatusDto: BatchUserStatusDto): Promise { try { this.logOperation('log', '开始批量修改用户状态', { operation: 'batch_update_user_status', userCount: batchUserStatusDto.userIds.length, newStatus: batchUserStatusDto.status, reason: batchUserStatusDto.reason }); const successUsers: UserStatusInfoDto[] = []; const failedUsers: Array<{ user_id: string; error: string }> = []; // 逐个处理用户状态修改 for (const userIdStr of batchUserStatusDto.userIds) { const result = await this.processSingleUserStatus(userIdStr, batchUserStatusDto.status); if (result.success) { successUsers.push(result.user); } else { failedUsers.push({ user_id: userIdStr, error: (result as { success: false; error: string }).error }); } } // 构建批量操作结果 const operationResult: BatchOperationResultDto = { success_users: successUsers, failed_users: failedUsers, success_count: successUsers.length, failed_count: failedUsers.length, total_count: batchUserStatusDto.userIds.length }; this.logOperation('log', '批量修改用户状态完成', { operation: 'batch_update_user_status', successCount: operationResult.success_count, failedCount: operationResult.failed_count, totalCount: operationResult.total_count }); return { success: true, data: { result: operationResult, reason: batchUserStatusDto.reason }, message: `批量用户状态修改完成,成功:${operationResult.success_count},失败:${operationResult.failed_count}` }; } catch (error) { this.logOperation('error', '批量修改用户状态失败', { operation: 'batch_update_user_status', error: error instanceof Error ? error.message : String(error) }); return { success: false, message: '批量用户状态修改失败', error_code: 'BATCH_USER_STATUS_UPDATE_FAILED' }; } } /** * 计算用户状态统计 * * @param users 用户列表 * @returns 状态统计结果 */ private calculateUserStatusStats(users: Users[]) { const stats = { active: 0, inactive: 0, locked: 0, banned: 0, deleted: 0, pending: 0, total: users.length }; users.forEach((user: Users) => { const status = user.status || UserStatus.ACTIVE; switch (status) { case UserStatus.ACTIVE: stats.active++; break; case UserStatus.INACTIVE: stats.inactive++; break; case UserStatus.LOCKED: stats.locked++; break; case UserStatus.BANNED: stats.banned++; break; case UserStatus.DELETED: stats.deleted++; break; case UserStatus.PENDING: stats.pending++; break; } }); return stats; } /** * 获取用户状态统计 * * 功能描述: * 获取各种用户状态的数量统计信息 * * 业务逻辑: * 1. 查询所有用户 * 2. 按状态分组统计 * 3. 计算各状态数量 * 4. 返回统计结果 * * @returns 状态统计信息 */ async getUserStatusStats(): Promise { try { this.logOperation('log', '开始获取用户状态统计', { operation: 'get_user_status_stats' }); // 查询所有用户(这里可以优化为直接查询统计信息) const allUsers = await this.usersService.findAll(USER_QUERY_LIMITS.MAX_USERS_FOR_STATS, 0); // 计算各状态数量 const stats = this.calculateUserStatusStats(allUsers); this.logOperation('log', '用户状态统计获取成功', { operation: 'get_user_status_stats', stats }); return { success: true, data: { stats, timestamp: getCurrentTimestamp() }, message: '用户状态统计获取成功' }; } catch (error) { this.logOperation('error', '获取用户状态统计失败', { operation: 'get_user_status_stats', error: error instanceof Error ? error.message : String(error) }); return { success: false, message: '用户状态统计获取失败', error_code: 'USER_STATUS_STATS_FAILED' }; } } }