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

@@ -0,0 +1,179 @@
/**
* 超时拦截器
*
* 功能描述:
* - 实现API接口的超时控制逻辑
* - 在超时时自动取消请求并返回错误
* - 记录超时事件的详细日志
*
* 使用场景:
* - 全局超时控制
* - 防止资源泄漏
* - 提升系统稳定性
*
* @author kiro-ai
* @version 1.0.0
* @since 2025-12-24
*/
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
RequestTimeoutException,
Logger
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable, throwError, TimeoutError } from 'rxjs';
import { catchError, timeout } from 'rxjs/operators';
import { TIMEOUT_KEY, TimeoutConfig } from '../decorators/timeout.decorator';
/**
* 超时响应接口
*/
interface TimeoutResponse {
/** 请求是否成功 */
success: boolean;
/** 响应消息 */
message: string;
/** 错误代码 */
error_code: string;
/** 超时信息 */
timeout_info: {
/** 超时时间(毫秒) */
timeout_ms: number;
/** 超时发生时间 */
timestamp: string;
};
}
@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
private readonly logger = new Logger(TimeoutInterceptor.name);
constructor(private readonly reflector: Reflector) {}
/**
* 拦截器处理函数
*
* 业务逻辑:
* 1. 获取超时配置
* 2. 应用超时控制
* 3. 处理超时异常
* 4. 记录超时日志
*
* @param context 执行上下文
* @param next 调用处理器
* @returns 可观察对象
*/
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// 1. 获取超时配置
const timeoutConfig = this.getTimeoutConfig(context);
if (!timeoutConfig) {
// 没有配置超时,直接执行
return next.handle();
}
// 2. 获取请求信息用于日志记录
const request = context.switchToHttp().getRequest();
const startTime = Date.now();
// 3. 应用超时控制
return next.handle().pipe(
timeout(timeoutConfig.timeout),
catchError((error) => {
if (error instanceof TimeoutError) {
// 4. 处理超时异常
const duration = Date.now() - startTime;
// 5. 记录超时日志
if (timeoutConfig.logTimeout !== false) {
this.logger.warn('请求超时', {
operation: 'request_timeout',
method: request.method,
url: request.url,
timeout_ms: timeoutConfig.timeout,
actual_duration_ms: duration,
userAgent: request.get('User-Agent'),
ip: request.ip,
timestamp: new Date().toISOString()
});
}
// 6. 构建超时响应
const timeoutResponse: TimeoutResponse = {
success: false,
message: timeoutConfig.message || '请求超时,请稍后重试',
error_code: 'REQUEST_TIMEOUT',
timeout_info: {
timeout_ms: timeoutConfig.timeout,
timestamp: new Date().toISOString()
}
};
// 7. 抛出超时异常
return throwError(() => new RequestTimeoutException(timeoutResponse));
}
// 其他异常直接抛出
return throwError(() => error);
})
);
}
/**
* 获取超时配置
*
* @param context 执行上下文
* @returns 超时配置或null
*/
private getTimeoutConfig(context: ExecutionContext): TimeoutConfig | null {
// 从方法装饰器获取配置
const methodConfig = this.reflector.get<TimeoutConfig>(
TIMEOUT_KEY,
context.getHandler()
);
if (methodConfig) {
return methodConfig;
}
// 从类装饰器获取配置
const classConfig = this.reflector.get<TimeoutConfig>(
TIMEOUT_KEY,
context.getClass()
);
return classConfig || null;
}
/**
* 获取默认超时配置
*
* @returns 默认超时配置
*/
private getDefaultTimeoutConfig(): TimeoutConfig {
return {
timeout: 30000, // 默认30秒
message: '请求超时,请稍后重试',
logTimeout: true
};
}
/**
* 验证超时配置
*
* @param config 超时配置
* @returns 是否有效
*/
private isValidTimeoutConfig(config: TimeoutConfig): boolean {
return (
config &&
typeof config.timeout === 'number' &&
config.timeout > 0 &&
config.timeout <= 600000 // 最大10分钟
);
}
}