feat(gateway/chat): 新增聊天网关模块

范围:src/gateway/chat/
- 新增 ChatWebSocketGateway WebSocket 网关,处理实时聊天通信
- 新增 ChatController HTTP 控制器,提供聊天历史和系统状态接口
- 新增 ChatGatewayModule 模块配置,整合网关层组件
- 新增请求/响应 DTO 定义,提供数据验证和类型约束
- 新增完整的单元测试覆盖
- 新增模块 README 文档,包含接口说明、核心特性和风险评估
This commit is contained in:
moyin
2026-01-14 19:11:25 +08:00
parent 3f3c29354e
commit 5bcf3cb678
8 changed files with 1702 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
/**
* 聊天网关层 DTO 定义
*
* 功能描述:
* - 定义聊天相关的数据传输对象
* - 用于 HTTP 和 WebSocket 请求的数据验证
* - 提供请求参数的类型约束和校验规则
*
* 最近修改:
* - 2026-01-14: 代码规范优化 - 清理未使用的导入 (修改者: moyin)
* - 2026-01-14: 代码规范优化 - 完善注释规范 (修改者: moyin)
*
* @author moyin
* @version 1.0.2
* @since 2026-01-14
* @lastModified 2026-01-14
*/
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsString, IsNotEmpty, IsOptional, IsNumber } from 'class-validator';
import { Type } from 'class-transformer';
/**
* 发送聊天消息请求 DTO
*/
export class SendChatMessageDto {
@ApiProperty({
description: '消息内容',
example: '大家好!我刚进入游戏',
maxLength: 1000
})
@IsString()
@IsNotEmpty()
content: string;
@ApiProperty({
description: '消息范围',
example: 'local',
enum: ['local', 'global'],
default: 'local'
})
@IsString()
@IsNotEmpty()
scope: string;
@ApiPropertyOptional({
description: '地图ID可选用于地图相关消息',
example: 'whale_port'
})
@IsOptional()
@IsString()
mapId?: string;
}
/**
* 获取聊天历史请求 DTO
*/
export class GetChatHistoryDto {
@ApiPropertyOptional({
description: '地图ID可选',
example: 'whale_port'
})
@IsOptional()
@IsString()
mapId?: string;
@ApiPropertyOptional({
description: '消息数量限制',
example: 50,
default: 50,
minimum: 1,
maximum: 100
})
@IsOptional()
@IsNumber()
@Type(() => Number)
limit?: number = 50;
@ApiPropertyOptional({
description: '偏移量(分页用)',
example: 0,
default: 0,
minimum: 0
})
@IsOptional()
@IsNumber()
@Type(() => Number)
offset?: number = 0;
}
/**
* WebSocket 登录消息 DTO
*/
export class WsLoginDto {
@IsString()
@IsNotEmpty()
token: string;
}
/**
* WebSocket 聊天消息 DTO
*/
export class WsChatMessageDto {
@IsString()
@IsNotEmpty()
content: string;
@IsString()
@IsOptional()
scope?: string;
}
/**
* WebSocket 位置更新 DTO
*/
export class WsPositionUpdateDto {
@IsNumber()
x: number;
@IsNumber()
y: number;
@IsString()
@IsNotEmpty()
mapId: string;
}