feat: 重构业务模块架构

- 新增auth模块处理认证逻辑
- 新增security模块处理安全相关功能
- 新增user-mgmt模块管理用户相关操作
- 新增shared模块存放共享组件
- 重构admin模块,添加DTO和Guards
- 为admin模块添加测试文件结构
This commit is contained in:
moyin
2025-12-24 18:04:30 +08:00
parent 85d488a508
commit 47a738067a
35 changed files with 3667 additions and 227 deletions

View File

@@ -11,12 +11,21 @@
* @since 2025-12-19
*/
import { Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
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/enums/user-status.enum';
import { UserStatusDto, BatchUserStatusDto } from '../user-mgmt/dto/user-status.dto';
import {
UserStatusResponseDto,
BatchUserStatusResponseDto,
UserStatusStatsResponseDto,
UserStatusInfoDto,
BatchOperationResultDto
} from '../user-mgmt/dto/user-status-response.dto';
export interface AdminApiResponse<T = any> {
success: boolean;
@@ -108,8 +117,318 @@ export class AdminService {
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<UserStatusResponseDto> {
try {
this.logger.log('开始修改用户状态', {
operation: 'update_user_status',
userId: userId.toString(),
newStatus: userStatusDto.status,
reason: userStatusDto.reason,
timestamp: new Date().toISOString()
});
// 1. 验证用户是否存在
const user = await this.usersService.findOne(userId);
if (!user) {
this.logger.warn('修改用户状态失败:用户不存在', {
operation: 'update_user_status',
userId: userId.toString()
});
throw new NotFoundException('用户不存在');
}
// 2. 检查状态变更的合法性
if (user.status === userStatusDto.status) {
this.logger.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.logger.log('用户状态修改成功', {
operation: 'update_user_status',
userId: userId.toString(),
oldStatus: user.status,
newStatus: userStatusDto.status,
reason: userStatusDto.reason,
timestamp: new Date().toISOString()
});
return {
success: true,
data: {
user: this.formatUserStatus(updatedUser),
reason: userStatusDto.reason
},
message: '用户状态修改成功'
};
} catch (error) {
this.logger.error('修改用户状态失败', {
operation: 'update_user_status',
userId: userId.toString(),
error: error instanceof Error ? error.message : String(error),
timestamp: new Date().toISOString()
});
if (error instanceof NotFoundException || error instanceof BadRequestException) {
throw error;
}
return {
success: false,
message: '用户状态修改失败',
error_code: 'USER_STATUS_UPDATE_FAILED'
};
}
}
/**
* 批量修改用户状态
*
* 功能描述:
* 管理员批量修改多个用户的账户状态
*
* 业务逻辑:
* 1. 验证用户ID列表
* 2. 逐个处理用户状态修改
* 3. 收集成功和失败的结果
* 4. 返回批量操作结果
*
* @param batchUserStatusDto 批量状态修改数据
* @returns 批量修改结果
*/
async batchUpdateUserStatus(batchUserStatusDto: BatchUserStatusDto): Promise<BatchUserStatusResponseDto> {
try {
this.logger.log('开始批量修改用户状态', {
operation: 'batch_update_user_status',
userCount: batchUserStatusDto.user_ids.length,
newStatus: batchUserStatusDto.status,
reason: batchUserStatusDto.reason,
timestamp: new Date().toISOString()
});
const successUsers: UserStatusInfoDto[] = [];
const failedUsers: Array<{ user_id: string; error: string }> = [];
// 1. 逐个处理用户状态修改
for (const userIdStr of batchUserStatusDto.user_ids) {
try {
const userId = BigInt(userIdStr);
// 2. 验证用户是否存在
const user = await this.usersService.findOne(userId);
if (!user) {
failedUsers.push({
user_id: userIdStr,
error: '用户不存在'
});
continue;
}
// 3. 检查状态是否需要变更
if (user.status === batchUserStatusDto.status) {
failedUsers.push({
user_id: userIdStr,
error: '用户状态未发生变化'
});
continue;
}
// 4. 更新用户状态
const updatedUser = await this.usersService.update(userId, {
status: batchUserStatusDto.status
});
successUsers.push(this.formatUserStatus(updatedUser));
} catch (error) {
failedUsers.push({
user_id: userIdStr,
error: error instanceof Error ? error.message : '未知错误'
});
}
}
// 5. 构建批量操作结果
const result: BatchOperationResultDto = {
success_users: successUsers,
failed_users: failedUsers,
success_count: successUsers.length,
failed_count: failedUsers.length,
total_count: batchUserStatusDto.user_ids.length
};
this.logger.log('批量修改用户状态完成', {
operation: 'batch_update_user_status',
successCount: result.success_count,
failedCount: result.failed_count,
totalCount: result.total_count,
timestamp: new Date().toISOString()
});
return {
success: true,
data: {
result,
reason: batchUserStatusDto.reason
},
message: `批量用户状态修改完成,成功:${result.success_count},失败:${result.failed_count}`
};
} catch (error) {
this.logger.error('批量修改用户状态失败', {
operation: 'batch_update_user_status',
error: error instanceof Error ? error.message : String(error),
timestamp: new Date().toISOString()
});
return {
success: false,
message: '批量用户状态修改失败',
error_code: 'BATCH_USER_STATUS_UPDATE_FAILED'
};
}
}
/**
* 获取用户状态统计
*
* 功能描述:
* 获取各种用户状态的数量统计信息
*
* 业务逻辑:
* 1. 查询所有用户
* 2. 按状态分组统计
* 3. 计算各状态数量
* 4. 返回统计结果
*
* @returns 状态统计信息
*/
async getUserStatusStats(): Promise<UserStatusStatsResponseDto> {
try {
this.logger.log('开始获取用户状态统计', {
operation: 'get_user_status_stats',
timestamp: new Date().toISOString()
});
// 1. 查询所有用户(这里可以优化为直接查询统计信息)
const allUsers = await this.usersService.findAll(10000, 0); // 假设最多1万用户
// 2. 按状态分组统计
const stats = {
active: 0,
inactive: 0,
locked: 0,
banned: 0,
deleted: 0,
pending: 0,
total: allUsers.length
};
// 3. 计算各状态数量
allUsers.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;
}
});
this.logger.log('用户状态统计获取成功', {
operation: 'get_user_status_stats',
stats,
timestamp: new Date().toISOString()
});
return {
success: true,
data: {
stats,
timestamp: new Date().toISOString()
},
message: '用户状态统计获取成功'
};
} catch (error) {
this.logger.error('获取用户状态统计失败', {
operation: 'get_user_status_stats',
error: error instanceof Error ? error.message : String(error),
timestamp: new Date().toISOString()
});
return {
success: false,
message: '用户状态统计获取失败',
error_code: 'USER_STATUS_STATS_FAILED'
};
}
}
}