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:
180
backend-nestjs/src/common/decorators/api-response.decorator.ts
Normal file
180
backend-nestjs/src/common/decorators/api-response.decorator.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import { applyDecorators, Type } from '@nestjs/common';
|
||||
import { ApiResponse, ApiResponseOptions } from '@nestjs/swagger';
|
||||
|
||||
/**
|
||||
* 标准API响应装饰器
|
||||
*/
|
||||
export const ApiStandardResponse = <TModel extends Type<any>>(
|
||||
model?: TModel,
|
||||
options?: Omit<ApiResponseOptions, 'schema'>
|
||||
) => {
|
||||
const baseSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
success: {
|
||||
type: 'boolean',
|
||||
description: '请求是否成功',
|
||||
example: true,
|
||||
},
|
||||
code: {
|
||||
type: 'number',
|
||||
description: 'HTTP状态码',
|
||||
example: 200,
|
||||
},
|
||||
msg: {
|
||||
type: 'string',
|
||||
description: '响应消息',
|
||||
example: '操作成功',
|
||||
},
|
||||
timestamp: {
|
||||
type: 'string',
|
||||
description: '响应时间戳',
|
||||
example: '2023-12-01T12:00:00.000Z',
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
description: '请求路径',
|
||||
example: '/api/users',
|
||||
},
|
||||
requestId: {
|
||||
type: 'string',
|
||||
description: '请求ID',
|
||||
example: 'uuid-string',
|
||||
},
|
||||
},
|
||||
required: ['success', 'code', 'msg'],
|
||||
};
|
||||
|
||||
if (model) {
|
||||
baseSchema.properties['data'] = {
|
||||
$ref: `#/components/schemas/${model.name}`,
|
||||
};
|
||||
} else {
|
||||
baseSchema.properties['data'] = {
|
||||
type: 'object',
|
||||
description: '响应数据',
|
||||
nullable: true,
|
||||
};
|
||||
}
|
||||
|
||||
return applyDecorators(
|
||||
ApiResponse({
|
||||
...options,
|
||||
schema: baseSchema,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 成功响应装饰器
|
||||
*/
|
||||
export const ApiSuccessResponse = <TModel extends Type<any>>(
|
||||
model?: TModel,
|
||||
description: string = '操作成功'
|
||||
) => {
|
||||
return ApiStandardResponse(model, {
|
||||
status: 200,
|
||||
description,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建成功响应装饰器
|
||||
*/
|
||||
export const ApiCreatedResponse = <TModel extends Type<any>>(
|
||||
model?: TModel,
|
||||
description: string = '创建成功'
|
||||
) => {
|
||||
return ApiStandardResponse(model, {
|
||||
status: 201,
|
||||
description,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 错误响应装饰器
|
||||
*/
|
||||
export const ApiErrorResponse = (
|
||||
status: number,
|
||||
description: string,
|
||||
errorCode?: string
|
||||
) => {
|
||||
const schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
success: {
|
||||
type: 'boolean',
|
||||
description: '请求是否成功',
|
||||
example: false,
|
||||
},
|
||||
code: {
|
||||
type: 'number',
|
||||
description: 'HTTP状态码',
|
||||
example: status,
|
||||
},
|
||||
msg: {
|
||||
type: 'string',
|
||||
description: '错误消息',
|
||||
example: description,
|
||||
},
|
||||
data: {
|
||||
type: 'object',
|
||||
nullable: true,
|
||||
example: null,
|
||||
},
|
||||
errorCode: {
|
||||
type: 'string',
|
||||
description: '错误代码',
|
||||
example: errorCode || 'ERROR',
|
||||
},
|
||||
timestamp: {
|
||||
type: 'string',
|
||||
description: '响应时间戳',
|
||||
example: '2023-12-01T12:00:00.000Z',
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
description: '请求路径',
|
||||
example: '/api/users',
|
||||
},
|
||||
requestId: {
|
||||
type: 'string',
|
||||
description: '请求ID',
|
||||
example: 'uuid-string',
|
||||
},
|
||||
},
|
||||
required: ['success', 'code', 'msg', 'errorCode'],
|
||||
};
|
||||
|
||||
return applyDecorators(
|
||||
ApiResponse({
|
||||
status,
|
||||
description,
|
||||
schema,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 常用错误响应装饰器
|
||||
*/
|
||||
export const ApiBadRequestResponse = (description: string = '请求参数错误') =>
|
||||
ApiErrorResponse(400, description, 'BAD_REQUEST');
|
||||
|
||||
export const ApiUnauthorizedResponse = (description: string = '未授权访问') =>
|
||||
ApiErrorResponse(401, description, 'UNAUTHORIZED');
|
||||
|
||||
export const ApiForbiddenResponse = (description: string = '禁止访问') =>
|
||||
ApiErrorResponse(403, description, 'FORBIDDEN');
|
||||
|
||||
export const ApiNotFoundResponse = (description: string = '资源不存在') =>
|
||||
ApiErrorResponse(404, description, 'NOT_FOUND');
|
||||
|
||||
export const ApiConflictResponse = (description: string = '资源冲突') =>
|
||||
ApiErrorResponse(409, description, 'CONFLICT');
|
||||
|
||||
export const ApiValidationResponse = (description: string = '请求参数验证失败') =>
|
||||
ApiErrorResponse(422, description, 'VALIDATION_FAILED');
|
||||
|
||||
export const ApiInternalServerErrorResponse = (description: string = '服务器内部错误') =>
|
||||
ApiErrorResponse(500, description, 'INTERNAL_SERVER_ERROR');
|
||||
34
backend-nestjs/src/common/decorators/cache.decorator.ts
Normal file
34
backend-nestjs/src/common/decorators/cache.decorator.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { SetMetadata } from '@nestjs/common';
|
||||
import { CACHE_KEY_METADATA, CACHE_TTL_METADATA } from '../interceptors/cache.interceptor';
|
||||
|
||||
/**
|
||||
* 缓存装饰器
|
||||
* @param key 缓存键
|
||||
* @param ttl 过期时间(秒),默认300秒
|
||||
*/
|
||||
export const Cache = (key: string, ttl: number = 300) => {
|
||||
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
|
||||
SetMetadata(CACHE_KEY_METADATA, key)(target, propertyKey, descriptor);
|
||||
SetMetadata(CACHE_TTL_METADATA, ttl)(target, propertyKey, descriptor);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 短时间缓存(1分钟)
|
||||
*/
|
||||
export const CacheShort = (key: string) => Cache(key, 60);
|
||||
|
||||
/**
|
||||
* 中等时间缓存(5分钟)
|
||||
*/
|
||||
export const CacheMedium = (key: string) => Cache(key, 300);
|
||||
|
||||
/**
|
||||
* 长时间缓存(30分钟)
|
||||
*/
|
||||
export const CacheLong = (key: string) => Cache(key, 1800);
|
||||
|
||||
/**
|
||||
* 超长时间缓存(2小时)
|
||||
*/
|
||||
export const CacheVeryLong = (key: string) => Cache(key, 7200);
|
||||
4
backend-nestjs/src/common/decorators/public.decorator.ts
Normal file
4
backend-nestjs/src/common/decorators/public.decorator.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { SetMetadata } from '@nestjs/common';
|
||||
|
||||
export const IS_PUBLIC_KEY = 'isPublic';
|
||||
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
|
||||
45
backend-nestjs/src/common/decorators/rate-limit.decorator.ts
Normal file
45
backend-nestjs/src/common/decorators/rate-limit.decorator.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { SetMetadata } from '@nestjs/common';
|
||||
|
||||
export const RATE_LIMIT_KEY = 'rate_limit';
|
||||
|
||||
export interface RateLimitOptions {
|
||||
windowMs?: number; // 时间窗口(毫秒)
|
||||
maxRequests?: number; // 最大请求数
|
||||
skipSuccessfulRequests?: boolean; // 是否跳过成功请求
|
||||
skipFailedRequests?: boolean; // 是否跳过失败请求
|
||||
keyGenerator?: (req: any) => string; // 自定义key生成器
|
||||
message?: string; // 自定义错误消息
|
||||
}
|
||||
|
||||
/**
|
||||
* 速率限制装饰器
|
||||
*/
|
||||
export const RateLimit = (options: RateLimitOptions = {}) =>
|
||||
SetMetadata(RATE_LIMIT_KEY, {
|
||||
windowMs: 15 * 60 * 1000, // 默认15分钟
|
||||
maxRequests: 100, // 默认100次请求
|
||||
skipSuccessfulRequests: false,
|
||||
skipFailedRequests: false,
|
||||
message: '请求频率过快,请稍后再试',
|
||||
...options,
|
||||
});
|
||||
|
||||
/**
|
||||
* 严格速率限制(用于敏感操作)
|
||||
*/
|
||||
export const StrictRateLimit = (maxRequests: number = 10, windowMs: number = 60 * 1000) =>
|
||||
RateLimit({
|
||||
maxRequests,
|
||||
windowMs,
|
||||
message: '操作频率过快,请稍后再试',
|
||||
});
|
||||
|
||||
/**
|
||||
* 宽松速率限制(用于一般查询)
|
||||
*/
|
||||
export const LooseRateLimit = (maxRequests: number = 1000, windowMs: number = 60 * 1000) =>
|
||||
RateLimit({
|
||||
maxRequests,
|
||||
windowMs,
|
||||
message: '请求次数过多,请稍后再试',
|
||||
});
|
||||
9
backend-nestjs/src/common/decorators/user.decorator.ts
Normal file
9
backend-nestjs/src/common/decorators/user.decorator.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
||||
import { Admin } from '@database/entities/admin.entity';
|
||||
|
||||
export const CurrentUser = createParamDecorator(
|
||||
(data: unknown, ctx: ExecutionContext): Admin => {
|
||||
const request = ctx.switchToHttp().getRequest();
|
||||
return request.user;
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user