refactor(data): move dto and schemas out of services directory

This commit is contained in:
2026-06-09 17:11:11 +08:00
parent 372b93fe45
commit 50940961ec
88 changed files with 279 additions and 356 deletions
@@ -0,0 +1,37 @@
/**
* 聊天历史响应 DTO
*/
import {
ChatHistoryResponseSchema,
type ChatHistoryResponseInput,
type ChatHistoryResponseData,
} from "@/data/schemas/chat/chat_history_response";
import { ChatMessage } from "./chat_message";
export class ChatHistoryResponse {
declare readonly messages: ChatMessage[];
declare readonly total: number;
declare readonly limit: number;
declare readonly offset: number;
private constructor(input: ChatHistoryResponseInput) {
const data = ChatHistoryResponseSchema.parse(input);
Object.assign(this, {
...data,
messages: data.messages.map((m) => ChatMessage.from(m)),
});
Object.freeze(this);
}
static from(input: ChatHistoryResponseInput): ChatHistoryResponse {
return new ChatHistoryResponse(input);
}
static fromJson(json: unknown): ChatHistoryResponse {
return ChatHistoryResponse.from(json as ChatHistoryResponseInput);
}
toJson(): ChatHistoryResponseData {
return ChatHistoryResponseSchema.parse(this);
}
}
+33
View File
@@ -0,0 +1,33 @@
/**
* 聊天历史中的单条消息 DTO
*/
import {
ChatMessageSchema,
type ChatMessageInput,
type ChatMessageData,
} from "@/data/schemas/chat/chat_message";
export class ChatMessage {
declare readonly role: string;
declare readonly content: string;
declare readonly id: string;
declare readonly createdAt: string;
private constructor(input: ChatMessageInput) {
const data = ChatMessageSchema.parse(input);
Object.assign(this, data);
Object.freeze(this);
}
static from(input: ChatMessageInput): ChatMessage {
return new ChatMessage(input);
}
static fromJson(json: unknown): ChatMessage {
return ChatMessage.from(json as ChatMessageInput);
}
toJson(): ChatMessageData {
return ChatMessageSchema.parse(this);
}
}
+40
View File
@@ -0,0 +1,40 @@
/**
* 发送消息响应 DTO
*/
import {
ChatSendResponseSchema,
type ChatSendResponseInput,
type ChatSendResponseData,
} from "@/data/schemas/chat/chat_send_response";
export class ChatSendResponse {
declare readonly mode: string;
declare readonly reply: string;
declare readonly voiceUrl: string;
declare readonly audioUrl: string;
declare readonly intimidadChange: number;
declare readonly newIntimacy: number;
declare readonly relationshipStage: string;
declare readonly currentMood: string;
declare readonly messageId: string;
declare readonly isGuest: boolean;
declare readonly timestamp: number;
private constructor(input: ChatSendResponseInput) {
const data = ChatSendResponseSchema.parse(input);
Object.assign(this, data);
Object.freeze(this);
}
static from(input: ChatSendResponseInput): ChatSendResponse {
return new ChatSendResponse(input);
}
static fromJson(json: unknown): ChatSendResponse {
return ChatSendResponse.from(json as ChatSendResponseInput);
}
toJson(): ChatSendResponseData {
return ChatSendResponseSchema.parse(this);
}
}
+31
View File
@@ -0,0 +1,31 @@
/**
* 消息同步响应 DTO
*/
import {
ChatSyncDataSchema,
type ChatSyncDataInput,
type ChatSyncDataData,
} from "@/data/schemas/chat/chat_sync_data";
export class ChatSyncData {
declare readonly syncedCount: number;
declare readonly totalHistory: number;
private constructor(input: ChatSyncDataInput) {
const data = ChatSyncDataSchema.parse(input);
Object.assign(this, data);
Object.freeze(this);
}
static from(input: ChatSyncDataInput): ChatSyncData {
return new ChatSyncData(input);
}
static fromJson(json: unknown): ChatSyncData {
return ChatSyncData.from(json as ChatSyncDataInput);
}
toJson(): ChatSyncDataData {
return ChatSyncDataSchema.parse(this);
}
}
+34
View File
@@ -0,0 +1,34 @@
/**
* 消息同步请求 DTO
*/
import {
ChatSyncRequestSchema,
type ChatSyncRequestInput,
type ChatSyncRequestData,
} from "@/data/schemas/chat/chat_sync_request";
import { SyncMessage } from "./sync_message";
export class ChatSyncRequest {
declare readonly messages: SyncMessage[];
private constructor(input: ChatSyncRequestInput) {
const data = ChatSyncRequestSchema.parse(input);
Object.assign(this, {
...data,
messages: data.messages.map((m) => SyncMessage.from(m)),
});
Object.freeze(this);
}
static from(input: ChatSyncRequestInput): ChatSyncRequest {
return new ChatSyncRequest(input);
}
static fromJson(json: unknown): ChatSyncRequest {
return ChatSyncRequest.from(json as ChatSyncRequestInput);
}
toJson(): ChatSyncRequestData {
return ChatSyncRequestSchema.parse(this);
}
}
+98
View File
@@ -0,0 +1,98 @@
/**
* 游客每日聊天配额数据 DTO
*/
import {
GuestChatQuotaSchema,
type GuestChatQuotaInput,
type GuestChatQuotaData,
} from "@/data/schemas/chat/guest_chat_quota";
export class GuestChatQuota {
// 静态常量
static readonly maxQuotaPerDay = 40;
static readonly maxQuotaPerDayTest = 4;
static readonly quotaWarningThreshold = 20;
static readonly quotaWarningThresholdTest = 2;
static readonly defaultTotalQuota = 50;
static readonly defaultTotalQuotaDev = 5;
static readonly quotaExhausted = 0;
declare readonly remaining: number;
declare readonly date: string;
private constructor(input: GuestChatQuotaInput) {
const data = GuestChatQuotaSchema.parse(input);
Object.assign(this, data);
Object.freeze(this);
}
static from(input: GuestChatQuotaInput): GuestChatQuota {
return new GuestChatQuota(input);
}
static fromJson(json: unknown): GuestChatQuota {
return GuestChatQuota.from(json as GuestChatQuotaInput);
}
/**
* 配额耗尽状态值
*/
static get exhausted(): number {
return GuestChatQuota.quotaExhausted;
}
/**
* 是否处于开发环境
*/
static get isDevelopment(): boolean {
return process.env.NODE_ENV !== "production";
}
/**
* 获取当前环境的配额警告阈值
*/
static get warningThreshold(): number {
return GuestChatQuota.isDevelopment
? GuestChatQuota.quotaWarningThresholdTest
: GuestChatQuota.quotaWarningThreshold;
}
/**
* 获取当前环境的每日最大配额
*/
static get threshold(): number {
return GuestChatQuota.isDevelopment
? GuestChatQuota.maxQuotaPerDayTest
: GuestChatQuota.maxQuotaPerDay;
}
/**
* 获取当前环境的总配额默认值
*/
static get totalQuotaDefault(): number {
return GuestChatQuota.isDevelopment
? GuestChatQuota.defaultTotalQuotaDev
: GuestChatQuota.defaultTotalQuota;
}
/**
* 创建初始配额实例
*/
static initial(todayString: string): GuestChatQuota {
return new GuestChatQuota({
remaining: GuestChatQuota.threshold,
date: todayString,
});
}
/**
* 是否需要重置(跨天)
*/
needsReset(todayString: string): boolean {
return this.date !== todayString;
}
toJson(): GuestChatQuotaData {
return GuestChatQuotaSchema.parse(this);
}
}
@@ -0,0 +1,37 @@
/**
* 图片上传响应 DTO
*/
import {
ImageUploadResponseSchema,
type ImageUploadResponseInput,
type ImageUploadResponseData,
} from "@/data/schemas/chat/image_upload_response";
export class ImageUploadResponse {
declare readonly success: boolean;
declare readonly imageId: string;
declare readonly thumbUrl: string;
declare readonly mediumUrl: string;
declare readonly originalUrl: string;
declare readonly width: number;
declare readonly height: number;
declare readonly bytes: number;
private constructor(input: ImageUploadResponseInput) {
const data = ImageUploadResponseSchema.parse(input);
Object.assign(this, data);
Object.freeze(this);
}
static from(input: ImageUploadResponseInput): ImageUploadResponse {
return new ImageUploadResponse(input);
}
static fromJson(json: unknown): ImageUploadResponse {
return ImageUploadResponse.from(json as ImageUploadResponseInput);
}
toJson(): ImageUploadResponseData {
return ImageUploadResponseSchema.parse(this);
}
}
+14
View File
@@ -0,0 +1,14 @@
/**
* @file Automatically generated by barrelsby.
*/
export * from "./chat_history_response";
export * from "./chat_message";
export * from "./chat_send_response";
export * from "./chat_sync_data";
export * from "./chat_sync_request";
export * from "./guest_chat_quota";
export * from "./image_upload_response";
export * from "./send_message_request";
export * from "./stt_data";
export * from "./sync_message";
+38
View File
@@ -0,0 +1,38 @@
/**
* 发送消息请求 DTO
*/
import {
SendMessageRequestSchema,
type SendMessageRequestInput,
type SendMessageRequestData,
} from "@/data/schemas/chat/send_message_request";
export class SendMessageRequest {
declare readonly message: string;
declare readonly image: string;
declare readonly imageId: string;
declare readonly imageThumbUrl: string;
declare readonly imageMediumUrl: string;
declare readonly imageOriginalUrl: string;
declare readonly imageWidth: number;
declare readonly imageHeight: number;
declare readonly useWebSocket: boolean;
private constructor(input: SendMessageRequestInput) {
const data = SendMessageRequestSchema.parse(input);
Object.assign(this, data);
Object.freeze(this);
}
static from(input: SendMessageRequestInput): SendMessageRequest {
return new SendMessageRequest(input);
}
static fromJson(json: unknown): SendMessageRequest {
return SendMessageRequest.from(json as SendMessageRequestInput);
}
toJson(): SendMessageRequestData {
return SendMessageRequestSchema.parse(this);
}
}
+30
View File
@@ -0,0 +1,30 @@
/**
* STT(语音转文字)响应 DTO
*/
import {
SttDataSchema,
type SttDataInput,
type SttDataData,
} from "@/data/schemas/chat/stt_data";
export class SttData {
declare readonly text: string;
private constructor(input: SttDataInput) {
const data = SttDataSchema.parse(input);
Object.assign(this, data);
Object.freeze(this);
}
static from(input: SttDataInput): SttData {
return new SttData(input);
}
static fromJson(json: unknown): SttData {
return SttData.from(json as SttDataInput);
}
toJson(): SttDataData {
return SttDataSchema.parse(this);
}
}
+32
View File
@@ -0,0 +1,32 @@
/**
* 待同步的单条消息 DTO
*/
import {
SyncMessageSchema,
type SyncMessageInput,
type SyncMessageData,
} from "@/data/schemas/chat/sync_message";
export class SyncMessage {
declare readonly role: string;
declare readonly content: string;
declare readonly timestamp: string;
private constructor(input: SyncMessageInput) {
const data = SyncMessageSchema.parse(input);
Object.assign(this, data);
Object.freeze(this);
}
static from(input: SyncMessageInput): SyncMessage {
return new SyncMessage(input);
}
static fromJson(json: unknown): SyncMessage {
return SyncMessage.from(json as SyncMessageInput);
}
toJson(): SyncMessageData {
return SyncMessageSchema.parse(this);
}
}