diff --git a/src/business/zulip/dto/chat.dto.ts b/src/business/zulip/dto/chat.dto.ts new file mode 100644 index 0000000..adc5eaf --- /dev/null +++ b/src/business/zulip/dto/chat.dto.ts @@ -0,0 +1,313 @@ +/** + * 聊天相关的 DTO 定义 + * + * @author angjustinl + * @version 1.0.0 + * @since 2025-01-07 + */ + +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { IsString, IsNotEmpty, IsOptional, IsNumber, IsBoolean, IsEnum, IsArray, ValidateNested } 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 ChatMessageResponseDto { + @ApiProperty({ + description: '是否成功', + example: true + }) + success: boolean; + + @ApiProperty({ + description: '消息ID', + example: 12345 + }) + messageId: number; + + @ApiProperty({ + description: '响应消息', + example: '消息发送成功' + }) + message: string; + + @ApiPropertyOptional({ + description: '错误信息(失败时)', + example: '消息内容不能为空' + }) + error?: 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; +} + +/** + * 聊天消息信息 DTO + */ +export class ChatMessageInfoDto { + @ApiProperty({ + description: '消息ID', + example: 12345 + }) + id: number; + + @ApiProperty({ + description: '发送者用户名', + example: 'Player_123' + }) + sender: string; + + @ApiProperty({ + description: '消息内容', + example: '大家好!' + }) + content: string; + + @ApiProperty({ + description: '消息范围', + example: 'local' + }) + scope: string; + + @ApiProperty({ + description: '地图ID', + example: 'whale_port' + }) + mapId: string; + + @ApiProperty({ + description: '发送时间', + example: '2025-01-07T14:30:00.000Z' + }) + timestamp: string; + + @ApiProperty({ + description: 'Zulip Stream 名称', + example: 'Whale Port' + }) + streamName: string; + + @ApiProperty({ + description: 'Zulip Topic 名称', + example: 'Game Chat' + }) + topicName: string; +} + +/** + * 聊天历史响应 DTO + */ +export class ChatHistoryResponseDto { + @ApiProperty({ + description: '是否成功', + example: true + }) + success: boolean; + + @ApiProperty({ + description: '消息列表', + type: [ChatMessageInfoDto] + }) + @ValidateNested({ each: true }) + @Type(() => ChatMessageInfoDto) + messages: ChatMessageInfoDto[]; + + @ApiProperty({ + description: '总消息数', + example: 150 + }) + total: number; + + @ApiProperty({ + description: '当前页消息数', + example: 50 + }) + count: number; + + @ApiPropertyOptional({ + description: '错误信息(失败时)', + example: '获取消息历史失败' + }) + error?: string; +} + +/** + * WebSocket 连接状态 DTO + */ +export class WebSocketStatusDto { + @ApiProperty({ + description: '总连接数', + example: 25 + }) + totalConnections: number; + + @ApiProperty({ + description: '已认证连接数', + example: 20 + }) + authenticatedConnections: number; + + @ApiProperty({ + description: '活跃会话数', + example: 18 + }) + activeSessions: number; + + @ApiProperty({ + description: '各地图在线人数', + example: { + 'whale_port': 8, + 'pumpkin_valley': 5, + 'novice_village': 7 + } + }) + mapPlayerCounts: Record; +} + +/** + * Zulip 集成状态 DTO + */ +export class ZulipIntegrationStatusDto { + @ApiProperty({ + description: 'Zulip 服务器连接状态', + example: true + }) + serverConnected: boolean; + + @ApiProperty({ + description: 'Zulip 服务器版本', + example: '11.4' + }) + serverVersion: string; + + @ApiProperty({ + description: '机器人账号状态', + example: true + }) + botAccountActive: boolean; + + @ApiProperty({ + description: '可用 Stream 数量', + example: 12 + }) + availableStreams: number; + + @ApiProperty({ + description: '游戏相关 Stream 列表', + example: ['Whale Port', 'Pumpkin Valley', 'Novice Village'] + }) + gameStreams: string[]; + + @ApiProperty({ + description: '最近24小时消息数', + example: 156 + }) + recentMessageCount: number; +} + +/** + * 系统状态响应 DTO + */ +export class SystemStatusResponseDto { + @ApiProperty({ + description: 'WebSocket 状态', + type: WebSocketStatusDto + }) + @ValidateNested() + @Type(() => WebSocketStatusDto) + websocket: WebSocketStatusDto; + + @ApiProperty({ + description: 'Zulip 集成状态', + type: ZulipIntegrationStatusDto + }) + @ValidateNested() + @Type(() => ZulipIntegrationStatusDto) + zulip: ZulipIntegrationStatusDto; + + @ApiProperty({ + description: '系统运行时间(秒)', + example: 86400 + }) + uptime: number; + + @ApiProperty({ + description: '内存使用情况', + example: { + used: '45.2 MB', + total: '64.0 MB', + percentage: 70.6 + } + }) + memory: { + used: string; + total: string; + percentage: number; + }; +} \ No newline at end of file