Initial commit: Telegram Management System
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
Full-stack web application for Telegram management - Frontend: Vue 3 + Vben Admin - Backend: NestJS - Features: User management, group broadcast, statistics 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
127
backend-nestjs/src/common/interceptors/response.interceptor.ts
Normal file
127
backend-nestjs/src/common/interceptors/response.interceptor.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import {
|
||||
Injectable,
|
||||
NestInterceptor,
|
||||
ExecutionContext,
|
||||
CallHandler,
|
||||
} from '@nestjs/common';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
|
||||
// 响应格式装饰器
|
||||
export const RESPONSE_MESSAGE_KEY = 'response_message';
|
||||
export const ResponseMessage = (message: string) =>
|
||||
Reflector.createDecorator<string>()[RESPONSE_MESSAGE_KEY](message);
|
||||
|
||||
// 跳过响应包装装饰器
|
||||
export const SKIP_RESPONSE_WRAP_KEY = 'skip_response_wrap';
|
||||
export const SkipResponseWrap = () =>
|
||||
Reflector.createDecorator<boolean>()[SKIP_RESPONSE_WRAP_KEY](true);
|
||||
|
||||
// 标准响应格式接口
|
||||
export interface ApiResponse<T = any> {
|
||||
success: boolean;
|
||||
code: number;
|
||||
data: T;
|
||||
msg: string;
|
||||
timestamp?: string;
|
||||
path?: string;
|
||||
requestId?: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ResponseInterceptor<T> implements NestInterceptor<T, ApiResponse<T>> {
|
||||
constructor(private readonly reflector: Reflector) {}
|
||||
|
||||
intercept(context: ExecutionContext, next: CallHandler): Observable<ApiResponse<T>> {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const response = context.switchToHttp().getResponse();
|
||||
|
||||
// 检查是否跳过响应包装
|
||||
const skipWrap = this.reflector.getAllAndOverride<boolean>(
|
||||
SKIP_RESPONSE_WRAP_KEY,
|
||||
[context.getHandler(), context.getClass()],
|
||||
);
|
||||
|
||||
if (skipWrap) {
|
||||
return next.handle();
|
||||
}
|
||||
|
||||
// 获取自定义响应消息
|
||||
const message = this.reflector.getAllAndOverride<string>(
|
||||
RESPONSE_MESSAGE_KEY,
|
||||
[context.getHandler(), context.getClass()],
|
||||
);
|
||||
|
||||
return next.handle().pipe(
|
||||
map((data) => {
|
||||
// 如果数据已经是标准格式,直接返回
|
||||
if (this.isApiResponse(data)) {
|
||||
return {
|
||||
...data,
|
||||
timestamp: new Date().toISOString(),
|
||||
path: request.url,
|
||||
requestId: request.headers['x-request-id'] || request.headers['request-id'],
|
||||
};
|
||||
}
|
||||
|
||||
// 包装成标准响应格式
|
||||
const result: ApiResponse<T> = {
|
||||
success: true,
|
||||
code: response.statusCode || 200,
|
||||
data: data,
|
||||
msg: message || this.getDefaultMessage(response.statusCode),
|
||||
timestamp: new Date().toISOString(),
|
||||
path: request.url,
|
||||
requestId: request.headers['x-request-id'] || request.headers['request-id'],
|
||||
};
|
||||
|
||||
return result;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查数据是否已经是API响应格式
|
||||
*/
|
||||
private isApiResponse(data: any): data is ApiResponse {
|
||||
return (
|
||||
data &&
|
||||
typeof data === 'object' &&
|
||||
'success' in data &&
|
||||
'code' in data &&
|
||||
'data' in data &&
|
||||
'msg' in data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据状态码获取默认消息
|
||||
*/
|
||||
private getDefaultMessage(statusCode: number): string {
|
||||
switch (statusCode) {
|
||||
case 200:
|
||||
return '操作成功';
|
||||
case 201:
|
||||
return '创建成功';
|
||||
case 204:
|
||||
return '操作成功';
|
||||
case 400:
|
||||
return '请求参数错误';
|
||||
case 401:
|
||||
return '未授权访问';
|
||||
case 403:
|
||||
return '禁止访问';
|
||||
case 404:
|
||||
return '资源不存在';
|
||||
case 409:
|
||||
return '资源冲突';
|
||||
case 422:
|
||||
return '请求参数验证失败';
|
||||
case 500:
|
||||
return '服务器内部错误';
|
||||
default:
|
||||
return '操作完成';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user