feat: Phase 1-3 全部完成 — 沙盒增强、学情分析、学习路径

This commit is contained in:
yuzhiran-dev
2026-05-18 09:48:51 +08:00
commit 11bb86854c
277 changed files with 37755 additions and 0 deletions
@@ -0,0 +1,31 @@
import { ExceptionFilter, Catch, ArgumentsHost, HttpException, HttpStatus, Logger } from '@nestjs/common';
import { Response } from 'express';
@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {
private readonly logger = new Logger(GlobalExceptionFilter.name);
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
let status = HttpStatus.INTERNAL_SERVER_ERROR;
let message = '服务器内部错误';
if (exception instanceof HttpException) {
status = exception.getStatus();
const res = exception.getResponse();
message = typeof res === 'string' ? res : (res as any).message || message;
if (Array.isArray(message)) message = message[0];
}
this.logger.error(`[${status}] ${message}`, exception instanceof Error ? exception.stack : '');
response.status(status).json({
code: status,
message,
data: null,
timestamp: new Date().toISOString(),
});
}
}
+2
View File
@@ -0,0 +1,2 @@
export { GlobalExceptionFilter } from './filters/global-exception.filter';
export { LoggingInterceptor } from './interceptors/logging.interceptor';
@@ -0,0 +1,22 @@
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
private readonly logger = new Logger('HTTP');
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const { method, url } = request;
const now = Date.now();
return next.handle().pipe(
tap(() => {
const response = context.switchToHttp().getResponse();
const ms = Date.now() - now;
this.logger.log(`${method} ${url} ${response.statusCode} ${ms}ms`);
}),
);
}
}