forked from datawhale/whale-town-end
feat(sql, auth, email, dto):重构邮箱验证流程,引入基于内存的用户服务,并改进 API 响应处理
* 新增完整的 API 状态码文档,并对测试模式进行特殊处理(`206 Partial Content`) * 重组 DTO 结构,引入 `app.dto.ts` 与 `error_response.dto.ts`,以实现统一、规范的响应格式 * 重构登录相关 DTO,优化命名与结构,提升可维护性 * 实现基于内存的用户服务(`users_memory.service.ts`),用于开发与测试环境 * 更新邮件服务,增强验证码生成逻辑,并支持测试模式自动识别 * 增强登录控制器与服务层的错误处理能力,统一响应行为 * 优化核心登录服务,强化参数校验并集成邮箱验证流程 * 新增 `@types/express` 依赖,提升 TypeScript 类型支持与开发体验 * 改进 `main.ts`,优化应用初始化流程与配置管理 * 在所有服务中统一错误处理机制,采用标准化的错误响应格式 * 实现测试模式(`206`)与生产环境邮件发送(`200`)之间的无缝切换
This commit is contained in:
72
src/dto/app.dto.ts
Normal file
72
src/dto/app.dto.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 应用状态响应 DTO
|
||||
*
|
||||
* 功能描述:
|
||||
* - 定义应用状态接口的响应格式
|
||||
* - 提供 Swagger 文档生成支持
|
||||
*
|
||||
* @author angjustinl
|
||||
* @version 1.0.0
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
/**
|
||||
* 应用状态响应 DTO
|
||||
*/
|
||||
export class AppStatusResponseDto {
|
||||
@ApiProperty({
|
||||
description: '服务名称',
|
||||
example: 'Pixel Game Server',
|
||||
type: String
|
||||
})
|
||||
service: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '服务版本',
|
||||
example: '1.0.0',
|
||||
type: String
|
||||
})
|
||||
version: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '运行状态',
|
||||
example: 'running',
|
||||
enum: ['running', 'starting', 'stopping', 'error'],
|
||||
type: String
|
||||
})
|
||||
status: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '当前时间戳',
|
||||
example: '2025-12-17T15:00:00.000Z',
|
||||
type: String,
|
||||
format: 'date-time'
|
||||
})
|
||||
timestamp: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '运行时间(秒)',
|
||||
example: 3600,
|
||||
type: Number,
|
||||
minimum: 0
|
||||
})
|
||||
uptime: number;
|
||||
|
||||
@ApiProperty({
|
||||
description: '运行环境',
|
||||
example: 'development',
|
||||
enum: ['development', 'production', 'test'],
|
||||
type: String
|
||||
})
|
||||
environment: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '存储模式',
|
||||
example: 'memory',
|
||||
enum: ['database', 'memory'],
|
||||
type: String
|
||||
})
|
||||
storage_mode: 'database' | 'memory';
|
||||
}
|
||||
56
src/dto/error_response.dto.ts
Normal file
56
src/dto/error_response.dto.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 通用错误响应 DTO
|
||||
*
|
||||
* 功能描述:
|
||||
* - 定义统一的错误响应格式
|
||||
* - 提供 Swagger 文档生成支持
|
||||
*
|
||||
* @author angjustinl
|
||||
* @version 1.0.0
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
/**
|
||||
* 通用错误响应 DTO
|
||||
*/
|
||||
export class ErrorResponseDto {
|
||||
@ApiProperty({
|
||||
description: 'HTTP 状态码',
|
||||
example: 500,
|
||||
type: Number
|
||||
})
|
||||
statusCode: number;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误消息',
|
||||
example: 'Internal server error',
|
||||
type: String
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误发生时间',
|
||||
example: '2025-12-17T15:00:00.000Z',
|
||||
type: String,
|
||||
format: 'date-time'
|
||||
})
|
||||
timestamp: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '请求路径',
|
||||
example: '/api/status',
|
||||
type: String,
|
||||
required: false
|
||||
})
|
||||
path?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误代码',
|
||||
example: 'INTERNAL_ERROR',
|
||||
type: String,
|
||||
required: false
|
||||
})
|
||||
error?: string;
|
||||
}
|
||||
374
src/dto/login.dto.ts
Normal file
374
src/dto/login.dto.ts
Normal file
@@ -0,0 +1,374 @@
|
||||
/**
|
||||
* 登录业务数据传输对象
|
||||
*
|
||||
* 功能描述:
|
||||
* - 定义登录相关API的请求数据结构
|
||||
* - 提供数据验证规则和错误提示
|
||||
* - 确保API接口的数据格式一致性
|
||||
*
|
||||
* @author moyin
|
||||
* @version 1.0.0
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
|
||||
import {
|
||||
IsString,
|
||||
IsEmail,
|
||||
IsPhoneNumber,
|
||||
IsNotEmpty,
|
||||
Length,
|
||||
IsOptional,
|
||||
Matches,
|
||||
IsNumberString
|
||||
} from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
/**
|
||||
* 登录请求DTO
|
||||
*/
|
||||
export class LoginDto {
|
||||
/**
|
||||
* 登录标识符
|
||||
* 支持用户名、邮箱或手机号登录
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '登录标识符,支持用户名、邮箱或手机号',
|
||||
example: 'testuser',
|
||||
minLength: 1,
|
||||
maxLength: 100
|
||||
})
|
||||
@IsString({ message: '登录标识符必须是字符串' })
|
||||
@IsNotEmpty({ message: '登录标识符不能为空' })
|
||||
@Length(1, 100, { message: '登录标识符长度需在1-100字符之间' })
|
||||
identifier: string;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '用户密码',
|
||||
example: 'password123',
|
||||
minLength: 1,
|
||||
maxLength: 128
|
||||
})
|
||||
@IsString({ message: '密码必须是字符串' })
|
||||
@IsNotEmpty({ message: '密码不能为空' })
|
||||
@Length(1, 128, { message: '密码长度需在1-128字符之间' })
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册请求DTO
|
||||
*/
|
||||
export class RegisterDto {
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '用户名,只能包含字母、数字和下划线',
|
||||
example: 'testuser',
|
||||
minLength: 1,
|
||||
maxLength: 50,
|
||||
pattern: '^[a-zA-Z0-9_]+$'
|
||||
})
|
||||
@IsString({ message: '用户名必须是字符串' })
|
||||
@IsNotEmpty({ message: '用户名不能为空' })
|
||||
@Length(1, 50, { message: '用户名长度需在1-50字符之间' })
|
||||
@Matches(/^[a-zA-Z0-9_]+$/, { message: '用户名只能包含字母、数字和下划线' })
|
||||
username: string;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '密码,必须包含字母和数字,长度8-128字符',
|
||||
example: 'password123',
|
||||
minLength: 8,
|
||||
maxLength: 128
|
||||
})
|
||||
@IsString({ message: '密码必须是字符串' })
|
||||
@IsNotEmpty({ message: '密码不能为空' })
|
||||
@Length(8, 128, { message: '密码长度需在8-128字符之间' })
|
||||
@Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '密码必须包含字母和数字' })
|
||||
password: string;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '用户昵称',
|
||||
example: '测试用户',
|
||||
minLength: 1,
|
||||
maxLength: 50
|
||||
})
|
||||
@IsString({ message: '昵称必须是字符串' })
|
||||
@IsNotEmpty({ message: '昵称不能为空' })
|
||||
@Length(1, 50, { message: '昵称长度需在1-50字符之间' })
|
||||
nickname: string;
|
||||
|
||||
/**
|
||||
* 邮箱(可选)
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '邮箱地址(可选)',
|
||||
example: 'test@example.com',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsEmail({}, { message: '邮箱格式不正确' })
|
||||
email?: string;
|
||||
|
||||
/**
|
||||
* 手机号(可选)
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '手机号码(可选)',
|
||||
example: '+8613800138000',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsPhoneNumber(null, { message: '手机号格式不正确' })
|
||||
phone?: string;
|
||||
|
||||
/**
|
||||
* 邮箱验证码(当提供邮箱时必填)
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '邮箱验证码,当提供邮箱时必填',
|
||||
example: '123456',
|
||||
pattern: '^\\d{6}$',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString({ message: '验证码必须是字符串' })
|
||||
@Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
|
||||
email_verification_code?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* GitHub OAuth登录请求DTO
|
||||
*/
|
||||
export class GitHubOAuthDto {
|
||||
/**
|
||||
* GitHub用户ID
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: 'GitHub用户ID',
|
||||
example: '12345678',
|
||||
minLength: 1,
|
||||
maxLength: 100
|
||||
})
|
||||
@IsString({ message: 'GitHub ID必须是字符串' })
|
||||
@IsNotEmpty({ message: 'GitHub ID不能为空' })
|
||||
@Length(1, 100, { message: 'GitHub ID长度需在1-100字符之间' })
|
||||
github_id: string;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: 'GitHub用户名',
|
||||
example: 'octocat',
|
||||
minLength: 1,
|
||||
maxLength: 50
|
||||
})
|
||||
@IsString({ message: '用户名必须是字符串' })
|
||||
@IsNotEmpty({ message: '用户名不能为空' })
|
||||
@Length(1, 50, { message: '用户名长度需在1-50字符之间' })
|
||||
username: string;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: 'GitHub显示名称',
|
||||
example: 'The Octocat',
|
||||
minLength: 1,
|
||||
maxLength: 50
|
||||
})
|
||||
@IsString({ message: '昵称必须是字符串' })
|
||||
@IsNotEmpty({ message: '昵称不能为空' })
|
||||
@Length(1, 50, { message: '昵称长度需在1-50字符之间' })
|
||||
nickname: string;
|
||||
|
||||
/**
|
||||
* 邮箱(可选)
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: 'GitHub邮箱地址(可选)',
|
||||
example: 'octocat@github.com',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsEmail({}, { message: '邮箱格式不正确' })
|
||||
email?: string;
|
||||
|
||||
/**
|
||||
* 头像URL(可选)
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: 'GitHub头像URL(可选)',
|
||||
example: 'https://github.com/images/error/octocat_happy.gif',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString({ message: '头像URL必须是字符串' })
|
||||
avatar_url?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 忘记密码请求DTO
|
||||
*/
|
||||
export class ForgotPasswordDto {
|
||||
/**
|
||||
* 邮箱或手机号
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '邮箱或手机号',
|
||||
example: 'test@example.com',
|
||||
minLength: 1,
|
||||
maxLength: 100
|
||||
})
|
||||
@IsString({ message: '标识符必须是字符串' })
|
||||
@IsNotEmpty({ message: '邮箱或手机号不能为空' })
|
||||
@Length(1, 100, { message: '标识符长度需在1-100字符之间' })
|
||||
identifier: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码请求DTO
|
||||
*/
|
||||
export class ResetPasswordDto {
|
||||
/**
|
||||
* 邮箱或手机号
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '邮箱或手机号',
|
||||
example: 'test@example.com',
|
||||
minLength: 1,
|
||||
maxLength: 100
|
||||
})
|
||||
@IsString({ message: '标识符必须是字符串' })
|
||||
@IsNotEmpty({ message: '邮箱或手机号不能为空' })
|
||||
@Length(1, 100, { message: '标识符长度需在1-100字符之间' })
|
||||
identifier: string;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '6位数字验证码',
|
||||
example: '123456',
|
||||
pattern: '^\\d{6}$'
|
||||
})
|
||||
@IsString({ message: '验证码必须是字符串' })
|
||||
@IsNotEmpty({ message: '验证码不能为空' })
|
||||
@Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
|
||||
verification_code: string;
|
||||
|
||||
/**
|
||||
* 新密码
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '新密码,必须包含字母和数字,长度8-128字符',
|
||||
example: 'newpassword123',
|
||||
minLength: 8,
|
||||
maxLength: 128
|
||||
})
|
||||
@IsString({ message: '新密码必须是字符串' })
|
||||
@IsNotEmpty({ message: '新密码不能为空' })
|
||||
@Length(8, 128, { message: '新密码长度需在8-128字符之间' })
|
||||
@Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '新密码必须包含字母和数字' })
|
||||
new_password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码请求DTO
|
||||
*/
|
||||
export class ChangePasswordDto {
|
||||
/**
|
||||
* 用户ID
|
||||
* 实际应用中应从JWT令牌中获取,这里为了演示放在请求体中
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '用户ID(实际应用中应从JWT令牌中获取)',
|
||||
example: '1'
|
||||
})
|
||||
@IsNumberString({}, { message: '用户ID必须是数字字符串' })
|
||||
@IsNotEmpty({ message: '用户ID不能为空' })
|
||||
user_id: string;
|
||||
|
||||
/**
|
||||
* 旧密码
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '当前密码',
|
||||
example: 'oldpassword123',
|
||||
minLength: 1,
|
||||
maxLength: 128
|
||||
})
|
||||
@IsString({ message: '旧密码必须是字符串' })
|
||||
@IsNotEmpty({ message: '旧密码不能为空' })
|
||||
@Length(1, 128, { message: '旧密码长度需在1-128字符之间' })
|
||||
old_password: string;
|
||||
|
||||
/**
|
||||
* 新密码
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '新密码,必须包含字母和数字,长度8-128字符',
|
||||
example: 'newpassword123',
|
||||
minLength: 8,
|
||||
maxLength: 128
|
||||
})
|
||||
@IsString({ message: '新密码必须是字符串' })
|
||||
@IsNotEmpty({ message: '新密码不能为空' })
|
||||
@Length(8, 128, { message: '新密码长度需在8-128字符之间' })
|
||||
@Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '新密码必须包含字母和数字' })
|
||||
new_password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮箱验证请求DTO
|
||||
*/
|
||||
export class EmailVerificationDto {
|
||||
/**
|
||||
* 邮箱地址
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '邮箱地址',
|
||||
example: 'test@example.com'
|
||||
})
|
||||
@IsEmail({}, { message: '邮箱格式不正确' })
|
||||
@IsNotEmpty({ message: '邮箱不能为空' })
|
||||
email: string;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '6位数字验证码',
|
||||
example: '123456',
|
||||
pattern: '^\\d{6}$'
|
||||
})
|
||||
@IsString({ message: '验证码必须是字符串' })
|
||||
@IsNotEmpty({ message: '验证码不能为空' })
|
||||
@Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
|
||||
verification_code: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮箱验证码请求DTO
|
||||
*/
|
||||
export class SendEmailVerificationDto {
|
||||
/**
|
||||
* 邮箱地址
|
||||
*/
|
||||
@ApiProperty({
|
||||
description: '邮箱地址',
|
||||
example: 'test@example.com'
|
||||
})
|
||||
@IsEmail({}, { message: '邮箱格式不正确' })
|
||||
@IsNotEmpty({ message: '邮箱不能为空' })
|
||||
email: string;
|
||||
}
|
||||
395
src/dto/login_response.dto.ts
Normal file
395
src/dto/login_response.dto.ts
Normal file
@@ -0,0 +1,395 @@
|
||||
/**
|
||||
* 登录业务响应数据传输对象
|
||||
*
|
||||
* 功能描述:
|
||||
* - 定义登录相关API的响应数据结构
|
||||
* - 提供Swagger文档生成支持
|
||||
* - 确保API响应的数据格式一致性
|
||||
*
|
||||
* @author moyin
|
||||
* @version 1.0.0
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
/**
|
||||
* 用户信息响应DTO
|
||||
*/
|
||||
export class UserInfoDto {
|
||||
@ApiProperty({
|
||||
description: '用户ID',
|
||||
example: '1'
|
||||
})
|
||||
id: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '用户名',
|
||||
example: 'testuser'
|
||||
})
|
||||
username: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '用户昵称',
|
||||
example: '测试用户'
|
||||
})
|
||||
nickname: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '邮箱地址',
|
||||
example: 'test@example.com',
|
||||
required: false
|
||||
})
|
||||
email?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '手机号码',
|
||||
example: '+8613800138000',
|
||||
required: false
|
||||
})
|
||||
phone?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '头像URL',
|
||||
example: 'https://example.com/avatar.jpg',
|
||||
required: false
|
||||
})
|
||||
avatar_url?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '用户角色',
|
||||
example: 1
|
||||
})
|
||||
role: number;
|
||||
|
||||
@ApiProperty({
|
||||
description: '创建时间',
|
||||
example: '2025-12-17T10:00:00.000Z'
|
||||
})
|
||||
created_at: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录响应数据DTO
|
||||
*/
|
||||
export class LoginResponseDataDto {
|
||||
@ApiProperty({
|
||||
description: '用户信息',
|
||||
type: UserInfoDto
|
||||
})
|
||||
user: UserInfoDto;
|
||||
|
||||
@ApiProperty({
|
||||
description: '访问令牌',
|
||||
example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
||||
})
|
||||
access_token: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '刷新令牌',
|
||||
example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
|
||||
required: false
|
||||
})
|
||||
refresh_token?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '是否为新用户',
|
||||
example: false,
|
||||
required: false
|
||||
})
|
||||
is_new_user?: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应消息',
|
||||
example: '登录成功'
|
||||
})
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录响应DTO
|
||||
*/
|
||||
export class LoginResponseDto {
|
||||
@ApiProperty({
|
||||
description: '请求是否成功',
|
||||
example: true
|
||||
})
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应数据',
|
||||
type: LoginResponseDataDto,
|
||||
required: false
|
||||
})
|
||||
data?: LoginResponseDataDto;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应消息',
|
||||
example: '登录成功'
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误代码',
|
||||
example: 'LOGIN_FAILED',
|
||||
required: false
|
||||
})
|
||||
error_code?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册响应DTO
|
||||
*/
|
||||
export class RegisterResponseDto {
|
||||
@ApiProperty({
|
||||
description: '请求是否成功',
|
||||
example: true
|
||||
})
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应数据',
|
||||
type: LoginResponseDataDto,
|
||||
required: false
|
||||
})
|
||||
data?: LoginResponseDataDto;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应消息',
|
||||
example: '注册成功'
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误代码',
|
||||
example: 'REGISTER_FAILED',
|
||||
required: false
|
||||
})
|
||||
error_code?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* GitHub OAuth响应DTO
|
||||
*/
|
||||
export class GitHubOAuthResponseDto {
|
||||
@ApiProperty({
|
||||
description: '请求是否成功',
|
||||
example: true
|
||||
})
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应数据',
|
||||
type: LoginResponseDataDto,
|
||||
required: false
|
||||
})
|
||||
data?: LoginResponseDataDto;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应消息',
|
||||
example: 'GitHub登录成功'
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误代码',
|
||||
example: 'GITHUB_OAUTH_FAILED',
|
||||
required: false
|
||||
})
|
||||
error_code?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 忘记密码响应数据DTO
|
||||
*/
|
||||
export class ForgotPasswordResponseDataDto {
|
||||
@ApiProperty({
|
||||
description: '验证码(仅用于演示,实际应用中不应返回)',
|
||||
example: '123456',
|
||||
required: false
|
||||
})
|
||||
verification_code?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '是否为测试模式',
|
||||
example: true,
|
||||
required: false
|
||||
})
|
||||
is_test_mode?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 忘记密码响应DTO
|
||||
*/
|
||||
export class ForgotPasswordResponseDto {
|
||||
@ApiProperty({
|
||||
description: '请求是否成功',
|
||||
example: false,
|
||||
examples: {
|
||||
success: {
|
||||
summary: '真实发送成功',
|
||||
value: true
|
||||
},
|
||||
testMode: {
|
||||
summary: '测试模式',
|
||||
value: false
|
||||
}
|
||||
}
|
||||
})
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应数据',
|
||||
type: ForgotPasswordResponseDataDto,
|
||||
required: false,
|
||||
examples: {
|
||||
success: {
|
||||
summary: '真实发送成功',
|
||||
value: {
|
||||
verification_code: '123456',
|
||||
is_test_mode: false
|
||||
}
|
||||
},
|
||||
testMode: {
|
||||
summary: '测试模式',
|
||||
value: {
|
||||
verification_code: '059174',
|
||||
is_test_mode: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
data?: ForgotPasswordResponseDataDto;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应消息',
|
||||
example: '⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。',
|
||||
examples: {
|
||||
success: {
|
||||
summary: '真实发送成功',
|
||||
value: '验证码已发送,请查收'
|
||||
},
|
||||
testMode: {
|
||||
summary: '测试模式',
|
||||
value: '⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。'
|
||||
}
|
||||
}
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误代码',
|
||||
example: 'TEST_MODE_ONLY',
|
||||
examples: {
|
||||
success: {
|
||||
summary: '真实发送成功',
|
||||
value: null
|
||||
},
|
||||
testMode: {
|
||||
summary: '测试模式',
|
||||
value: 'TEST_MODE_ONLY'
|
||||
},
|
||||
failed: {
|
||||
summary: '发送失败',
|
||||
value: 'SEND_CODE_FAILED'
|
||||
}
|
||||
},
|
||||
required: false
|
||||
})
|
||||
error_code?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用响应DTO(用于重置密码、修改密码等)
|
||||
*/
|
||||
export class CommonResponseDto {
|
||||
@ApiProperty({
|
||||
description: '请求是否成功',
|
||||
example: true
|
||||
})
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应消息',
|
||||
example: '操作成功'
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误代码',
|
||||
example: 'OPERATION_FAILED',
|
||||
required: false
|
||||
})
|
||||
error_code?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试模式邮件验证码响应DTO by angjustinl 2025-12-17
|
||||
*/
|
||||
export class TestModeEmailVerificationResponseDto {
|
||||
@ApiProperty({
|
||||
description: '请求是否成功(测试模式下为false)',
|
||||
example: false
|
||||
})
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应数据',
|
||||
example: {
|
||||
verification_code: '059174',
|
||||
is_test_mode: true
|
||||
}
|
||||
})
|
||||
data: {
|
||||
verification_code: string;
|
||||
is_test_mode: boolean;
|
||||
};
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应消息',
|
||||
example: '⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。'
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误代码',
|
||||
example: 'TEST_MODE_ONLY'
|
||||
})
|
||||
error_code: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功发送邮件验证码响应DTO
|
||||
*/
|
||||
export class SuccessEmailVerificationResponseDto {
|
||||
@ApiProperty({
|
||||
description: '请求是否成功',
|
||||
example: true
|
||||
})
|
||||
success: boolean;
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应数据',
|
||||
example: {
|
||||
verification_code: '123456',
|
||||
is_test_mode: false
|
||||
}
|
||||
})
|
||||
data: {
|
||||
verification_code: string;
|
||||
is_test_mode: boolean;
|
||||
};
|
||||
|
||||
@ApiProperty({
|
||||
description: '响应消息',
|
||||
example: '验证码已发送,请查收'
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: '错误代码',
|
||||
example: null,
|
||||
required: false
|
||||
})
|
||||
error_code?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user