diff --git a/src/data/api/auth_api.ts b/src/data/api/auth_api.ts index abc809ed..f08522f0 100644 --- a/src/data/api/auth_api.ts +++ b/src/data/api/auth_api.ts @@ -6,23 +6,21 @@ */ import { httpClient } from "./http_client"; import { ApiPath } from "./api_path"; -import { - AppleLoginRequest, - FacebookLoginRequest, - FbIdLoginRequest, - GoogleLoginRequest, - GuestLoginRequest, - GuestLoginResponse, - LoginRequest, - LoginResponse, - LogoutResponse, - RefreshTokenRequest, - RefreshTokenResponse, - RegisterRequest, - SendCodeRequest, - User, - type UserData, -} from "@/data/models"; +import { AppleLoginRequest } from "@/data/dto/auth/apple_login_request"; +import { FacebookLoginRequest } from "@/data/dto/auth/facebook_login_request"; +import { FbIdLoginRequest } from "@/data/dto/auth/fb_id_login_request"; +import { GoogleLoginRequest } from "@/data/dto/auth/google_login_request"; +import { GuestLoginRequest } from "@/data/dto/auth/guest_login_request"; +import { GuestLoginResponse } from "@/data/dto/auth/guest_login_response"; +import { LoginRequest } from "@/data/dto/auth/login_request"; +import { LoginResponse } from "@/data/dto/auth/login_response"; +import { LogoutResponse } from "@/data/dto/auth/logout_response"; +import { RefreshTokenRequest } from "@/data/dto/auth/refresh_token_request"; +import { RefreshTokenResponse } from "@/data/dto/auth/refresh_token_response"; +import { RegisterRequest } from "@/data/dto/auth/register_request"; +import { SendCodeRequest } from "@/data/dto/auth/send_code_request"; +import { User } from "@/data/dto/user/user"; +import type { UserData } from "@/data/schemas/user/user"; /** * 后端统一响应包装 diff --git a/src/data/api/chat_api.ts b/src/data/api/chat_api.ts index 3a70e985..2201047d 100644 --- a/src/data/api/chat_api.ts +++ b/src/data/api/chat_api.ts @@ -6,16 +6,14 @@ */ import { httpClient } from "./http_client"; import { ApiPath } from "./api_path"; -import { - ChatHistoryResponse, - ChatSendResponse, - ChatSyncData, - ChatSyncRequest, - ImageUploadResponse, - SendMessageRequest, - SttData, - SyncMessage, -} from "@/data/models"; +import { ChatHistoryResponse } from "@/data/dto/chat/chat_history_response"; +import { ChatSendResponse } from "@/data/dto/chat/chat_send_response"; +import { ChatSyncData } from "@/data/dto/chat/chat_sync_data"; +import { ChatSyncRequest } from "@/data/dto/chat/chat_sync_request"; +import { ImageUploadResponse } from "@/data/dto/chat/image_upload_response"; +import { SendMessageRequest } from "@/data/dto/chat/send_message_request"; +import { SttData } from "@/data/dto/chat/stt_data"; +import { SyncMessage } from "@/data/dto/chat/sync_message"; /** * 后端统一响应包装 @@ -74,9 +72,7 @@ export class ChatApi { /** * 同步游客消息 */ - async syncMessages( - messages: SyncMessage[] - ): Promise { + async syncMessages(messages: SyncMessage[]): Promise { const body = ChatSyncRequest.from({ messages }); const env = await httpClient>(ApiPath.chatSync, { method: "POST", diff --git a/src/data/api/metrics_api.ts b/src/data/api/metrics_api.ts index 1af9f9cd..d669d106 100644 --- a/src/data/api/metrics_api.ts +++ b/src/data/api/metrics_api.ts @@ -6,7 +6,8 @@ */ import { httpClient } from "./http_client"; import { ApiPath } from "./api_path"; -import { AppEvent, PwaEvent } from "@/data/models"; +import { AppEvent } from "@/data/dto/metrics/app_event"; +import { PwaEvent } from "@/data/dto/metrics/pwa_event"; /** * 后端统一响应包装 diff --git a/src/data/api/user_api.ts b/src/data/api/user_api.ts index 4fc3a4dd..aa53066e 100644 --- a/src/data/api/user_api.ts +++ b/src/data/api/user_api.ts @@ -6,14 +6,12 @@ */ import { httpClient } from "./http_client"; import { ApiPath } from "./api_path"; -import { - CreditsData, - CreditsHistoryData, - UpdateProfileRequest, - User, - UserStatsResponse, - type UserData, -} from "@/data/models"; +import { CreditsData } from "@/data/dto/user/credits_data"; +import { CreditsHistoryData } from "@/data/dto/user/credits_history_data"; +import { UpdateProfileRequest } from "@/data/dto/user/update_profile_request"; +import { User } from "@/data/dto/user/user"; +import { UserStatsResponse } from "@/data/dto/user/user_stats_response"; +import type { UserData } from "@/data/schemas/user/user"; /** * 后端统一响应包装 diff --git a/src/data/models/auth/apple_login_request.ts b/src/data/dto/auth/apple_login_request.ts similarity index 61% rename from src/data/models/auth/apple_login_request.ts rename to src/data/dto/auth/apple_login_request.ts index 8b084f06..218a38ad 100644 --- a/src/data/models/auth/apple_login_request.ts +++ b/src/data/dto/auth/apple_login_request.ts @@ -1,16 +1,11 @@ /** - * Apple 登录请求 - * 原始 Dart: AppleLoginRequest (lib/data/models/auth/auth_request.dart) + * Apple 登录请求 DTO */ -import { z } from "zod"; - -export const AppleLoginRequestSchema = z.object({ - identityToken: z.string(), - platform: z.string(), -}); - -export type AppleLoginRequestInput = z.input; -export type AppleLoginRequestData = z.output; +import { + AppleLoginRequestSchema, + type AppleLoginRequestInput, + type AppleLoginRequestData, +} from "@/data/schemas/auth/apple_login_request"; export class AppleLoginRequest { declare readonly identityToken: string; diff --git a/src/data/models/auth/facebook_login_request.ts b/src/data/dto/auth/facebook_login_request.ts similarity index 60% rename from src/data/models/auth/facebook_login_request.ts rename to src/data/dto/auth/facebook_login_request.ts index 78617f57..2a96eb59 100644 --- a/src/data/models/auth/facebook_login_request.ts +++ b/src/data/dto/auth/facebook_login_request.ts @@ -1,17 +1,11 @@ /** - * Facebook 登录请求 - * 原始 Dart: FacebookLoginRequest (lib/data/models/auth/auth_request.dart) + * Facebook 登录请求 DTO */ -import { z } from "zod"; - -export const FacebookLoginRequestSchema = z.object({ - accessToken: z.string(), - platform: z.string(), - guestId: z.string().default(""), -}); - -export type FacebookLoginRequestInput = z.input; -export type FacebookLoginRequestData = z.output; +import { + FacebookLoginRequestSchema, + type FacebookLoginRequestInput, + type FacebookLoginRequestData, +} from "@/data/schemas/auth/facebook_login_request"; export class FacebookLoginRequest { declare readonly accessToken: string; diff --git a/src/data/models/auth/fb_id_login_request.ts b/src/data/dto/auth/fb_id_login_request.ts similarity index 60% rename from src/data/models/auth/fb_id_login_request.ts rename to src/data/dto/auth/fb_id_login_request.ts index 0925173a..f0f26430 100644 --- a/src/data/models/auth/fb_id_login_request.ts +++ b/src/data/dto/auth/fb_id_login_request.ts @@ -1,16 +1,11 @@ /** - * Facebook ID 登录请求 - * 原始 Dart: FbIdLoginRequest (lib/data/models/auth/auth_request.dart) + * Facebook ID 登录请求 DTO */ -import { z } from "zod"; - -export const FbIdLoginRequestSchema = z.object({ - fbId: z.string(), - avatarUrl: z.string().default(""), -}); - -export type FbIdLoginRequestInput = z.input; -export type FbIdLoginRequestData = z.output; +import { + FbIdLoginRequestSchema, + type FbIdLoginRequestInput, + type FbIdLoginRequestData, +} from "@/data/schemas/auth/fb_id_login_request"; export class FbIdLoginRequest { declare readonly fbId: string; diff --git a/src/data/models/auth/google_login_request.ts b/src/data/dto/auth/google_login_request.ts similarity index 61% rename from src/data/models/auth/google_login_request.ts rename to src/data/dto/auth/google_login_request.ts index 1c3eb419..0dbcba5b 100644 --- a/src/data/models/auth/google_login_request.ts +++ b/src/data/dto/auth/google_login_request.ts @@ -1,17 +1,11 @@ /** - * Google 登录请求 - * 原始 Dart: GoogleLoginRequest (lib/data/models/auth/auth_request.dart) + * Google 登录请求 DTO */ -import { z } from "zod"; - -export const GoogleLoginRequestSchema = z.object({ - idToken: z.string(), - platform: z.string(), - guestId: z.string().default(""), -}); - -export type GoogleLoginRequestInput = z.input; -export type GoogleLoginRequestData = z.output; +import { + GoogleLoginRequestSchema, + type GoogleLoginRequestInput, + type GoogleLoginRequestData, +} from "@/data/schemas/auth/google_login_request"; export class GoogleLoginRequest { declare readonly idToken: string; diff --git a/src/data/models/auth/guest_login_request.ts b/src/data/dto/auth/guest_login_request.ts similarity index 61% rename from src/data/models/auth/guest_login_request.ts rename to src/data/dto/auth/guest_login_request.ts index 4898ab33..d01274cd 100644 --- a/src/data/models/auth/guest_login_request.ts +++ b/src/data/dto/auth/guest_login_request.ts @@ -1,15 +1,11 @@ /** - * 游客登录请求 - * 原始 Dart: GuestLoginRequest (lib/data/models/auth/auth_request.dart) + * 游客登录请求 DTO */ -import { z } from "zod"; - -export const GuestLoginRequestSchema = z.object({ - deviceId: z.string(), -}); - -export type GuestLoginRequestInput = z.input; -export type GuestLoginRequestData = z.output; +import { + GuestLoginRequestSchema, + type GuestLoginRequestInput, + type GuestLoginRequestData, +} from "@/data/schemas/auth/guest_login_request"; export class GuestLoginRequest { declare readonly deviceId: string; diff --git a/src/data/dto/auth/guest_login_response.ts b/src/data/dto/auth/guest_login_response.ts new file mode 100644 index 00000000..ea9cb903 --- /dev/null +++ b/src/data/dto/auth/guest_login_response.ts @@ -0,0 +1,40 @@ +/** + * 游客登录响应 DTO + */ +import { + GuestLoginResponseSchema, + type GuestLoginResponseInput, + type GuestLoginResponseData, +} from "@/data/schemas/auth/guest_login_response"; +import { User } from "@/data/dto/user/user"; + +export class GuestLoginResponse { + declare readonly token: string; + declare readonly deviceId: string; + declare readonly userId: string; + declare readonly isDeviceUser: boolean; + declare readonly expiresIn: number; + declare readonly user: User; + + private constructor(input: GuestLoginResponseInput) { + const parsed = GuestLoginResponseSchema.parse(input); + Object.assign(this, { + ...parsed, + user: parsed.user ? User.fromJson(parsed.user) : User.empty(), + }); + Object.freeze(this); + } + + static from(input: GuestLoginResponseInput): GuestLoginResponse { + return new GuestLoginResponse(input); + } + + static fromJson(json: unknown): GuestLoginResponse { + return GuestLoginResponse.from(json as GuestLoginResponseInput); + } + + toJson(): GuestLoginResponseData { + const data = GuestLoginResponseSchema.parse(this); + return data; + } +} diff --git a/src/data/models/auth/login_request.ts b/src/data/dto/auth/login_request.ts similarity index 58% rename from src/data/models/auth/login_request.ts rename to src/data/dto/auth/login_request.ts index 8b37fff3..4c69cba4 100644 --- a/src/data/models/auth/login_request.ts +++ b/src/data/dto/auth/login_request.ts @@ -1,19 +1,11 @@ /** - * 登录请求 - 支持用户名或邮箱登录 - * 原始 Dart: LoginRequest (lib/data/models/auth/auth_request.dart) + * 登录请求 DTO */ -import { z } from "zod"; - -export const LoginRequestSchema = z.object({ - email: z.string().default(""), - username: z.string().default(""), - password: z.string(), - platform: z.string(), - guestId: z.string().default(""), -}); - -export type LoginRequestInput = z.input; -export type LoginRequestData = z.output; +import { + LoginRequestSchema, + type LoginRequestInput, + type LoginRequestData, +} from "@/data/schemas/auth/login_request"; export class LoginRequest { declare readonly email: string; diff --git a/src/data/models/auth/login_response.ts b/src/data/dto/auth/login_response.ts similarity index 55% rename from src/data/models/auth/login_response.ts rename to src/data/dto/auth/login_response.ts index 9df10d32..1cbe9fea 100644 --- a/src/data/models/auth/login_response.ts +++ b/src/data/dto/auth/login_response.ts @@ -1,18 +1,12 @@ /** - * 登录响应 - * 原始 Dart: LoginResponse (lib/data/models/auth/auth_response.dart) + * 登录响应 DTO */ -import { z } from "zod"; -import { User, UserSchema } from "../user/user"; - -export const LoginResponseSchema = z.object({ - user: UserSchema, - token: z.string(), - refreshToken: z.string().default(""), -}); - -export type LoginResponseInput = z.input; -export type LoginResponseData = z.output; +import { + LoginResponseSchema, + type LoginResponseInput, + type LoginResponseData, +} from "@/data/schemas/auth/login_response"; +import { User } from "@/data/dto/user/user"; export class LoginResponse { declare readonly user: User; @@ -21,7 +15,10 @@ export class LoginResponse { private constructor(input: LoginResponseInput) { const data = LoginResponseSchema.parse(input); - Object.assign(this, data); + Object.assign(this, { + ...data, + user: User.fromJson(data.user), + }); Object.freeze(this); } diff --git a/src/data/models/auth/logout_response.ts b/src/data/dto/auth/logout_response.ts similarity index 60% rename from src/data/models/auth/logout_response.ts rename to src/data/dto/auth/logout_response.ts index 57a943d5..53a922de 100644 --- a/src/data/models/auth/logout_response.ts +++ b/src/data/dto/auth/logout_response.ts @@ -1,15 +1,11 @@ /** - * 退出登录响应 - * 原始 Dart: LogoutResponse (lib/data/models/auth/auth_response.dart) + * 退出登录响应 DTO */ -import { z } from "zod"; - -export const LogoutResponseSchema = z.object({ - success: z.boolean().default(true), -}); - -export type LogoutResponseInput = z.input; -export type LogoutResponseData = z.output; +import { + LogoutResponseSchema, + type LogoutResponseInput, + type LogoutResponseData, +} from "@/data/schemas/auth/logout_response"; export class LogoutResponse { declare readonly success: boolean; diff --git a/src/data/models/auth/refresh_token_request.ts b/src/data/dto/auth/refresh_token_request.ts similarity index 61% rename from src/data/models/auth/refresh_token_request.ts rename to src/data/dto/auth/refresh_token_request.ts index 2fa504f7..96cd1d47 100644 --- a/src/data/models/auth/refresh_token_request.ts +++ b/src/data/dto/auth/refresh_token_request.ts @@ -1,15 +1,11 @@ /** - * 刷新 Token 请求 - * 原始 Dart: RefreshTokenRequest (lib/data/models/auth/auth_request.dart) + * 刷新 Token 请求 DTO */ -import { z } from "zod"; - -export const RefreshTokenRequestSchema = z.object({ - refreshToken: z.string(), -}); - -export type RefreshTokenRequestInput = z.input; -export type RefreshTokenRequestData = z.output; +import { + RefreshTokenRequestSchema, + type RefreshTokenRequestInput, + type RefreshTokenRequestData, +} from "@/data/schemas/auth/refresh_token_request"; export class RefreshTokenRequest { declare readonly refreshToken: string; diff --git a/src/data/models/auth/refresh_token_response.ts b/src/data/dto/auth/refresh_token_response.ts similarity index 61% rename from src/data/models/auth/refresh_token_response.ts rename to src/data/dto/auth/refresh_token_response.ts index 2e8635af..0508a305 100644 --- a/src/data/models/auth/refresh_token_response.ts +++ b/src/data/dto/auth/refresh_token_response.ts @@ -1,17 +1,11 @@ /** - * 刷新 Token 响应 - * 原始 Dart: RefreshTokenResponse (lib/data/models/auth/auth_response.dart) + * 刷新 Token 响应 DTO */ -import { z } from "zod"; - -export const RefreshTokenResponseSchema = z.object({ - token: z.string(), - refreshToken: z.string(), - userId: z.string(), -}); - -export type RefreshTokenResponseInput = z.input; -export type RefreshTokenResponseData = z.output; +import { + RefreshTokenResponseSchema, + type RefreshTokenResponseInput, + type RefreshTokenResponseData, +} from "@/data/schemas/auth/refresh_token_response"; export class RefreshTokenResponse { declare readonly token: string; diff --git a/src/data/models/auth/register_request.ts b/src/data/dto/auth/register_request.ts similarity index 61% rename from src/data/models/auth/register_request.ts rename to src/data/dto/auth/register_request.ts index 63608ee5..856ed5a3 100644 --- a/src/data/models/auth/register_request.ts +++ b/src/data/dto/auth/register_request.ts @@ -1,19 +1,11 @@ /** - * 注册请求 - * 原始 Dart: RegisterRequest (lib/data/models/auth/auth_request.dart) + * 注册请求 DTO */ -import { z } from "zod"; - -export const RegisterRequestSchema = z.object({ - username: z.string(), - email: z.string(), - password: z.string(), - platform: z.string(), - guestId: z.string().default(""), -}); - -export type RegisterRequestInput = z.input; -export type RegisterRequestData = z.output; +import { + RegisterRequestSchema, + type RegisterRequestInput, + type RegisterRequestData, +} from "@/data/schemas/auth/register_request"; export class RegisterRequest { declare readonly username: string; diff --git a/src/data/models/auth/send_code_request.ts b/src/data/dto/auth/send_code_request.ts similarity index 61% rename from src/data/models/auth/send_code_request.ts rename to src/data/dto/auth/send_code_request.ts index 454392b5..cbd0e54a 100644 --- a/src/data/models/auth/send_code_request.ts +++ b/src/data/dto/auth/send_code_request.ts @@ -1,15 +1,11 @@ /** - * 发送验证码请求 - * 原始 Dart: SendCodeRequest (lib/data/models/auth/auth_request.dart) + * 发送验证码请求 DTO */ -import { z } from "zod"; - -export const SendCodeRequestSchema = z.object({ - email: z.string(), -}); - -export type SendCodeRequestInput = z.input; -export type SendCodeRequestData = z.output; +import { + SendCodeRequestSchema, + type SendCodeRequestInput, + type SendCodeRequestData, +} from "@/data/schemas/auth/send_code_request"; export class SendCodeRequest { declare readonly email: string; diff --git a/src/data/models/chat/chat_history_response.ts b/src/data/dto/chat/chat_history_response.ts similarity index 54% rename from src/data/models/chat/chat_history_response.ts rename to src/data/dto/chat/chat_history_response.ts index 2781ab14..6b4abee6 100644 --- a/src/data/models/chat/chat_history_response.ts +++ b/src/data/dto/chat/chat_history_response.ts @@ -1,19 +1,12 @@ /** - * 聊天历史响应 - * 原始 Dart: ChatHistoryResponse (lib/data/models/chat/chat_response.dart) + * 聊天历史响应 DTO */ -import { z } from "zod"; -import { ChatMessage, ChatMessageSchema } from "./chat_message"; - -export const ChatHistoryResponseSchema = z.object({ - messages: z.array(ChatMessageSchema), - total: z.number().default(0), - limit: z.number(), - offset: z.number(), -}); - -export type ChatHistoryResponseInput = z.input; -export type ChatHistoryResponseData = z.output; +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[]; @@ -23,7 +16,10 @@ export class ChatHistoryResponse { private constructor(input: ChatHistoryResponseInput) { const data = ChatHistoryResponseSchema.parse(input); - Object.assign(this, data); + Object.assign(this, { + ...data, + messages: data.messages.map((m) => ChatMessage.from(m)), + }); Object.freeze(this); } diff --git a/src/data/models/chat/chat_message.ts b/src/data/dto/chat/chat_message.ts similarity index 59% rename from src/data/models/chat/chat_message.ts rename to src/data/dto/chat/chat_message.ts index ae1d440e..87dbc0e6 100644 --- a/src/data/models/chat/chat_message.ts +++ b/src/data/dto/chat/chat_message.ts @@ -1,18 +1,11 @@ /** - * 聊天历史中的单条消息 - * 原始 Dart: ChatMessage (lib/data/models/chat/chat_response.dart) + * 聊天历史中的单条消息 DTO */ -import { z } from "zod"; - -export const ChatMessageSchema = z.object({ - role: z.string(), - content: z.string(), - id: z.string().default(""), - createdAt: z.string().default(""), -}); - -export type ChatMessageInput = z.input; -export type ChatMessageData = z.output; +import { + ChatMessageSchema, + type ChatMessageInput, + type ChatMessageData, +} from "@/data/schemas/chat/chat_message"; export class ChatMessage { declare readonly role: string; diff --git a/src/data/models/chat/chat_send_response.ts b/src/data/dto/chat/chat_send_response.ts similarity index 54% rename from src/data/models/chat/chat_send_response.ts rename to src/data/dto/chat/chat_send_response.ts index 248dc684..a1523c4f 100644 --- a/src/data/models/chat/chat_send_response.ts +++ b/src/data/dto/chat/chat_send_response.ts @@ -1,32 +1,18 @@ /** - * 发送消息响应 - * 原始 Dart: ChatSendResponse (lib/data/models/chat/chat_response.dart) + * 发送消息响应 DTO */ -import { z } from "zod"; - -export const ChatSendResponseSchema = z.object({ - mode: z.string().default(""), - reply: z.string(), - voiceUrl: z.string().default(""), - audioUrl: z.string().default(""), - intimacyChange: z.number().default(0), - newIntimacy: z.number().default(0), - relationshipStage: z.string(), - currentMood: z.string().default(""), - messageId: z.string(), - isGuest: z.boolean().default(false), - timestamp: z.number().default(0), -}); - -export type ChatSendResponseInput = z.input; -export type ChatSendResponseData = z.output; +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 intimacyChange: number; + declare readonly intimidadChange: number; declare readonly newIntimacy: number; declare readonly relationshipStage: string; declare readonly currentMood: string; diff --git a/src/data/models/chat/chat_sync_data.ts b/src/data/dto/chat/chat_sync_data.ts similarity index 61% rename from src/data/models/chat/chat_sync_data.ts rename to src/data/dto/chat/chat_sync_data.ts index 3f40e100..24b3effc 100644 --- a/src/data/models/chat/chat_sync_data.ts +++ b/src/data/dto/chat/chat_sync_data.ts @@ -1,16 +1,11 @@ /** - * 消息同步响应 - * 原始 Dart: ChatSyncData (lib/data/models/chat/chat_sync.dart) + * 消息同步响应 DTO */ -import { z } from "zod"; - -export const ChatSyncDataSchema = z.object({ - syncedCount: z.number(), - totalHistory: z.number(), -}); - -export type ChatSyncDataInput = z.input; -export type ChatSyncDataData = z.output; +import { + ChatSyncDataSchema, + type ChatSyncDataInput, + type ChatSyncDataData, +} from "@/data/schemas/chat/chat_sync_data"; export class ChatSyncData { declare readonly syncedCount: number; diff --git a/src/data/models/chat/chat_sync_request.ts b/src/data/dto/chat/chat_sync_request.ts similarity index 53% rename from src/data/models/chat/chat_sync_request.ts rename to src/data/dto/chat/chat_sync_request.ts index d4d7fc2e..9427170f 100644 --- a/src/data/models/chat/chat_sync_request.ts +++ b/src/data/dto/chat/chat_sync_request.ts @@ -1,23 +1,22 @@ /** - * 消息同步请求 - * 原始 Dart: ChatSyncRequest (lib/data/models/chat/chat_sync.dart) + * 消息同步请求 DTO */ -import { z } from "zod"; -import { SyncMessage, SyncMessageSchema } from "./sync_message"; - -export const ChatSyncRequestSchema = z.object({ - messages: z.array(SyncMessageSchema), -}); - -export type ChatSyncRequestInput = z.input; -export type ChatSyncRequestData = z.output; +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); + Object.assign(this, { + ...data, + messages: data.messages.map((m) => SyncMessage.from(m)), + }); Object.freeze(this); } diff --git a/src/data/models/chat/guest_chat_quota.ts b/src/data/dto/chat/guest_chat_quota.ts similarity index 70% rename from src/data/models/chat/guest_chat_quota.ts rename to src/data/dto/chat/guest_chat_quota.ts index 8a16c152..ebbed3de 100644 --- a/src/data/models/chat/guest_chat_quota.ts +++ b/src/data/dto/chat/guest_chat_quota.ts @@ -1,25 +1,13 @@ /** - * 游客每日聊天配额数据 - * 原始 Dart: GuestChatQuota (lib/data/models/chat/guest_chat_quota.dart) - * - * 注:保留原始 Dart 中的静态常量与运行时环境判断方法。 - * `process.env.NODE_ENV` 替代 Dart 的 `AppEnvUtil.isDevelopment`。 - * `initial()` 工厂方法与 `needReset` 实例方法保留。 + * 游客每日聊天配额数据 DTO */ -import { z } from "zod"; - -export const GuestChatQuotaSchema = z.object({ - remaining: z.number(), - date: z.string(), -}); - -export type GuestChatQuotaInput = z.input; -export type GuestChatQuotaData = z.output; +import { + GuestChatQuotaSchema, + type GuestChatQuotaInput, + type GuestChatQuotaData, +} from "@/data/schemas/chat/guest_chat_quota"; export class GuestChatQuota { - declare readonly remaining: number; - declare readonly date: string; - // 静态常量 static readonly maxQuotaPerDay = 40; static readonly maxQuotaPerDayTest = 4; @@ -29,6 +17,9 @@ export class GuestChatQuota { 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); @@ -43,12 +34,8 @@ export class GuestChatQuota { return GuestChatQuota.from(json as GuestChatQuotaInput); } - toJson(): GuestChatQuotaData { - return GuestChatQuotaSchema.parse(this); - } - /** - * 配额耗尽状态值(便捷引用) + * 配额耗尽状态值 */ static get exhausted(): number { return GuestChatQuota.quotaExhausted; @@ -56,7 +43,6 @@ export class GuestChatQuota { /** * 是否处于开发环境 - * 通过 `process.env.NODE_ENV` 判断,替代 Dart 中的 `AppEnvUtil.isDevelopment` */ static get isDevelopment(): boolean { return process.env.NODE_ENV !== "production"; @@ -91,7 +77,6 @@ export class GuestChatQuota { /** * 创建初始配额实例 - * @param todayString 当天日期字符串(YYYY-MM-DD),由调用方提供 */ static initial(todayString: string): GuestChatQuota { return new GuestChatQuota({ @@ -102,9 +87,12 @@ export class GuestChatQuota { /** * 是否需要重置(跨天) - * @param todayString 当天日期字符串(YYYY-MM-DD),由调用方提供 */ needsReset(todayString: string): boolean { return this.date !== todayString; } + + toJson(): GuestChatQuotaData { + return GuestChatQuotaSchema.parse(this); + } } diff --git a/src/data/models/chat/image_upload_response.ts b/src/data/dto/chat/image_upload_response.ts similarity index 60% rename from src/data/models/chat/image_upload_response.ts rename to src/data/dto/chat/image_upload_response.ts index 221919f8..edbebbef 100644 --- a/src/data/models/chat/image_upload_response.ts +++ b/src/data/dto/chat/image_upload_response.ts @@ -1,22 +1,11 @@ /** - * 图片上传响应 - * 原始 Dart: ImageUploadResponse (lib/data/models/chat/image_upload_response.dart) + * 图片上传响应 DTO */ -import { z } from "zod"; - -export const ImageUploadResponseSchema = z.object({ - success: z.boolean().default(true), - imageId: z.string(), - thumbUrl: z.string(), - mediumUrl: z.string(), - originalUrl: z.string(), - width: z.number(), - height: z.number(), - bytes: z.number(), -}); - -export type ImageUploadResponseInput = z.input; -export type ImageUploadResponseData = z.output; +import { + ImageUploadResponseSchema, + type ImageUploadResponseInput, + type ImageUploadResponseData, +} from "@/data/schemas/chat/image_upload_response"; export class ImageUploadResponse { declare readonly success: boolean; diff --git a/src/data/models/chat/send_message_request.ts b/src/data/dto/chat/send_message_request.ts similarity index 55% rename from src/data/models/chat/send_message_request.ts rename to src/data/dto/chat/send_message_request.ts index 436f0e3b..41ad8f04 100644 --- a/src/data/models/chat/send_message_request.ts +++ b/src/data/dto/chat/send_message_request.ts @@ -1,23 +1,11 @@ /** - * 发送消息请求 - 用于 /api/chat/send 接口 - * 原始 Dart: SendMessageRequest (lib/data/models/chat/send_message_request.dart) + * 发送消息请求 DTO */ -import { z } from "zod"; - -export const SendMessageRequestSchema = z.object({ - message: z.string().default(""), - image: z.string().default(""), - imageId: z.string().default(""), - imageThumbUrl: z.string().default(""), - imageMediumUrl: z.string().default(""), - imageOriginalUrl: z.string().default(""), - imageWidth: z.number().default(0), - imageHeight: z.number().default(0), - useWebSocket: z.boolean().default(false), -}); - -export type SendMessageRequestInput = z.input; -export type SendMessageRequestData = z.output; +import { + SendMessageRequestSchema, + type SendMessageRequestInput, + type SendMessageRequestData, +} from "@/data/schemas/chat/send_message_request"; export class SendMessageRequest { declare readonly message: string; diff --git a/src/data/models/chat/stt_data.ts b/src/data/dto/chat/stt_data.ts similarity index 60% rename from src/data/models/chat/stt_data.ts rename to src/data/dto/chat/stt_data.ts index 7f1f23f8..a54d47e5 100644 --- a/src/data/models/chat/stt_data.ts +++ b/src/data/dto/chat/stt_data.ts @@ -1,15 +1,11 @@ /** - * STT(语音转文字)响应 - * 原始 Dart: SttData (lib/data/models/chat/stt_response.dart) + * STT(语音转文字)响应 DTO */ -import { z } from "zod"; - -export const SttDataSchema = z.object({ - text: z.string(), -}); - -export type SttDataInput = z.input; -export type SttDataData = z.output; +import { + SttDataSchema, + type SttDataInput, + type SttDataData, +} from "@/data/schemas/chat/stt_data"; export class SttData { declare readonly text: string; diff --git a/src/data/models/chat/sync_message.ts b/src/data/dto/chat/sync_message.ts similarity index 61% rename from src/data/models/chat/sync_message.ts rename to src/data/dto/chat/sync_message.ts index 8cd5dccf..e037a5a8 100644 --- a/src/data/models/chat/sync_message.ts +++ b/src/data/dto/chat/sync_message.ts @@ -1,17 +1,11 @@ /** - * 待同步的单条消息 - * 原始 Dart: SyncMessage (lib/data/models/chat/chat_sync.dart) + * 待同步的单条消息 DTO */ -import { z } from "zod"; - -export const SyncMessageSchema = z.object({ - role: z.string(), - content: z.string(), - timestamp: z.string(), -}); - -export type SyncMessageInput = z.input; -export type SyncMessageData = z.output; +import { + SyncMessageSchema, + type SyncMessageInput, + type SyncMessageData, +} from "@/data/schemas/chat/sync_message"; export class SyncMessage { declare readonly role: string; diff --git a/src/data/models/index.ts b/src/data/dto/index.ts similarity index 92% rename from src/data/models/index.ts rename to src/data/dto/index.ts index 98d8c74a..bf51c511 100644 --- a/src/data/models/index.ts +++ b/src/data/dto/index.ts @@ -1,7 +1,9 @@ /** - * @file Automatically generated by barrelsby. + * DTO - 集中导出 + * + * 不可变运行时类(API 层使用) + * 原始 Dart: lib/data/models/ */ - export * from "./auth/apple_login_request"; export * from "./auth/facebook_login_request"; export * from "./auth/fb_id_login_request"; @@ -15,6 +17,7 @@ export * from "./auth/refresh_token_request"; export * from "./auth/refresh_token_response"; export * from "./auth/register_request"; export * from "./auth/send_code_request"; + export * from "./chat/chat_history_response"; export * from "./chat/chat_message"; export * from "./chat/chat_send_response"; @@ -25,8 +28,10 @@ export * from "./chat/image_upload_response"; export * from "./chat/send_message_request"; export * from "./chat/stt_data"; export * from "./chat/sync_message"; + export * from "./metrics/app_event"; export * from "./metrics/pwa_event"; + export * from "./user/avatar_data"; export * from "./user/credits_data"; export * from "./user/credits_history_data"; diff --git a/src/data/models/metrics/app_event.ts b/src/data/dto/metrics/app_event.ts similarity index 58% rename from src/data/models/metrics/app_event.ts rename to src/data/dto/metrics/app_event.ts index 61c4dd17..daacdd83 100644 --- a/src/data/models/metrics/app_event.ts +++ b/src/data/dto/metrics/app_event.ts @@ -1,17 +1,11 @@ /** - * 应用事件上报请求 - 用于 /api/data/report-user-info 接口 - * 原始 Dart: AppEvent (lib/data/models/metrics/app_event.dart) + * 应用事件上报请求 DTO */ -import { z } from "zod"; - -export const AppEventSchema = z.object({ - userId: z.string(), - browser: z.string(), - userAgent: z.string(), -}); - -export type AppEventInput = z.input; -export type AppEventData = z.output; +import { + AppEventSchema, + type AppEventInput, + type AppEventData, +} from "@/data/schemas/metrics/app_event"; export class AppEvent { declare readonly userId: string; diff --git a/src/data/models/metrics/pwa_event.ts b/src/data/dto/metrics/pwa_event.ts similarity index 56% rename from src/data/models/metrics/pwa_event.ts rename to src/data/dto/metrics/pwa_event.ts index 13656969..95e33720 100644 --- a/src/data/models/metrics/pwa_event.ts +++ b/src/data/dto/metrics/pwa_event.ts @@ -1,19 +1,11 @@ /** - * PWA 事件上报请求 - 用于 /api/metrics/pwa/event 接口 - * 原始 Dart: PwaEvent (lib/data/models/metrics/pwa_event.dart) + * PWA 事件上报请求 DTO */ -import { z } from "zod"; - -export const PwaEventSchema = z.object({ - deviceId: z.string(), - deviceType: z.string(), - timestamp: z.number(), - pwaInstalled: z.boolean().default(false), - pwaSupported: z.boolean().default(false), -}); - -export type PwaEventInput = z.input; -export type PwaEventData = z.output; +import { + PwaEventSchema, + type PwaEventInput, + type PwaEventData, +} from "@/data/schemas/metrics/pwa_event"; export class PwaEvent { declare readonly deviceId: string; diff --git a/src/data/dto/user/avatar_data.ts b/src/data/dto/user/avatar_data.ts new file mode 100644 index 00000000..edb2dcc8 --- /dev/null +++ b/src/data/dto/user/avatar_data.ts @@ -0,0 +1,31 @@ +/** + * 头像数据 DTO + */ +import { + AvatarDataSchema, + type AvatarDataInput, + type AvatarDataData, +} from "@/data/schemas/user/avatar_data"; + +export class AvatarData { + declare readonly avatarUrl: string; + declare readonly userId: string; + + private constructor(input: AvatarDataInput) { + const data = AvatarDataSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: AvatarDataInput): AvatarData { + return new AvatarData(input); + } + + static fromJson(json: unknown): AvatarData { + return AvatarData.from(json as AvatarDataInput); + } + + toJson(): AvatarDataData { + return AvatarDataSchema.parse(this); + } +} diff --git a/src/data/dto/user/credits_data.ts b/src/data/dto/user/credits_data.ts new file mode 100644 index 00000000..095c3dfd --- /dev/null +++ b/src/data/dto/user/credits_data.ts @@ -0,0 +1,31 @@ +/** + * 积分数据 DTO + */ +import { + CreditsDataSchema, + type CreditsDataInput, + type CreditsDataData, +} from "@/data/schemas/user/credits_data"; + +export class CreditsData { + declare readonly userId: string; + declare readonly dolBalance: number; + + private constructor(input: CreditsDataInput) { + const data = CreditsDataSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: CreditsDataInput): CreditsData { + return new CreditsData(input); + } + + static fromJson(json: unknown): CreditsData { + return CreditsData.from(json as CreditsDataInput); + } + + toJson(): CreditsDataData { + return CreditsDataSchema.parse(this); + } +} diff --git a/src/data/dto/user/credits_history_data.ts b/src/data/dto/user/credits_history_data.ts new file mode 100644 index 00000000..6fcec0bb --- /dev/null +++ b/src/data/dto/user/credits_history_data.ts @@ -0,0 +1,33 @@ +/** + * 积分历史记录 DTO + */ +import { + CreditsHistoryDataSchema, + type CreditsHistoryDataInput, + type CreditsHistoryDataData, +} from "@/data/schemas/user/credits_history_data"; + +export class CreditsHistoryData { + declare readonly records: Record[]; + declare readonly total: number; + declare readonly limit: number; + declare readonly offset: number; + + private constructor(input: CreditsHistoryDataInput) { + const data = CreditsHistoryDataSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: CreditsHistoryDataInput): CreditsHistoryData { + return new CreditsHistoryData(input); + } + + static fromJson(json: unknown): CreditsHistoryData { + return CreditsHistoryData.from(json as CreditsHistoryDataInput); + } + + toJson(): CreditsHistoryDataData { + return CreditsHistoryDataSchema.parse(this); + } +} diff --git a/src/data/dto/user/personality_traits.ts b/src/data/dto/user/personality_traits.ts new file mode 100644 index 00000000..8802a2c7 --- /dev/null +++ b/src/data/dto/user/personality_traits.ts @@ -0,0 +1,34 @@ +/** + * 个性特征 DTO + */ +import { + PersonalityTraitsSchema, + type PersonalityTraitsInput, + type PersonalityTraitsData, +} from "@/data/schemas/user/personality_traits"; + +export class PersonalityTraits { + declare readonly cheerful: number; + declare readonly caring: number; + declare readonly playful: number; + declare readonly serious: number; + declare readonly romantic: number; + + private constructor(input: PersonalityTraitsInput) { + const data = PersonalityTraitsSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: PersonalityTraitsInput): PersonalityTraits { + return new PersonalityTraits(input); + } + + static fromJson(json: unknown): PersonalityTraits { + return PersonalityTraits.from(json as PersonalityTraitsInput); + } + + toJson(): PersonalityTraitsData { + return PersonalityTraitsSchema.parse(this); + } +} diff --git a/src/data/dto/user/recent_memory.ts b/src/data/dto/user/recent_memory.ts new file mode 100644 index 00000000..8d363810 --- /dev/null +++ b/src/data/dto/user/recent_memory.ts @@ -0,0 +1,33 @@ +/** + * 最近记忆 DTO + */ +import { + RecentMemorySchema, + type RecentMemoryInput, + type RecentMemoryData, +} from "@/data/schemas/user/recent_memory"; + +export class RecentMemory { + declare readonly type: string; + declare readonly content: string; + declare readonly importance: number; + declare readonly createdAt: string; + + private constructor(input: RecentMemoryInput) { + const data = RecentMemorySchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: RecentMemoryInput): RecentMemory { + return new RecentMemory(input); + } + + static fromJson(json: unknown): RecentMemory { + return RecentMemory.from(json as RecentMemoryInput); + } + + toJson(): RecentMemoryData { + return RecentMemorySchema.parse(this); + } +} diff --git a/src/data/dto/user/update_profile_request.ts b/src/data/dto/user/update_profile_request.ts new file mode 100644 index 00000000..deb3f0df --- /dev/null +++ b/src/data/dto/user/update_profile_request.ts @@ -0,0 +1,33 @@ +/** + * 更新个人资料请求 DTO + */ +import { + UpdateProfileRequestSchema, + type UpdateProfileRequestInput, + type UpdateProfileRequestData, +} from "@/data/schemas/user/update_profile_request"; + +export class UpdateProfileRequest { + declare readonly username: string; + declare readonly nickname: string; + declare readonly preferredLanguage: string; + declare readonly currentMood: string; + + private constructor(input: UpdateProfileRequestInput) { + const data = UpdateProfileRequestSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: UpdateProfileRequestInput): UpdateProfileRequest { + return new UpdateProfileRequest(input); + } + + static fromJson(json: unknown): UpdateProfileRequest { + return UpdateProfileRequest.from(json as UpdateProfileRequestInput); + } + + toJson(): UpdateProfileRequestData { + return UpdateProfileRequestSchema.parse(this); + } +} diff --git a/src/data/dto/user/user.ts b/src/data/dto/user/user.ts new file mode 100644 index 00000000..b3c13e90 --- /dev/null +++ b/src/data/dto/user/user.ts @@ -0,0 +1,59 @@ +/** + * 用户 DTO + */ +import { + UserSchema, + type UserInput, + type UserData, +} from "@/data/schemas/user/user"; +import { PersonalityTraits } from "./personality_traits"; + +export class User { + declare readonly id: string; + declare readonly username: string; + declare readonly email: string; + declare readonly platform: string; + declare readonly intimacy: number; + declare readonly dolBalance: number; + declare readonly relationshipStage: string; + declare readonly currentMood: string; + declare readonly personalityTraits: PersonalityTraits; + declare readonly preferredLanguage: string; + declare readonly createdAt: string; + declare readonly lastMessageAt: string; + declare readonly avatarUrl: string; + declare readonly loginProvider: string; + declare readonly isGuest: boolean; + + private constructor(input: UserInput) { + const data = UserSchema.parse(input); + Object.assign(this, { + ...data, + personalityTraits: PersonalityTraits.from(data.personalityTraits), + }); + Object.freeze(this); + } + + static from(input: UserInput): User { + return new User(input); + } + + static fromJson(json: unknown): User { + return User.from(json as UserInput); + } + + /** + * 创建一个具有空 id/username 的 User 实例(用于可选 user 字段的默认占位) + */ + static empty(): User { + return new User({ id: "", username: "" }); + } + + toJson(): UserData { + const { personalityTraits, ...rest } = this; + return { + ...rest, + personalityTraits: personalityTraits.toJson(), + }; + } +} diff --git a/src/data/dto/user/user_stats_response.ts b/src/data/dto/user/user_stats_response.ts new file mode 100644 index 00000000..fa25ebe4 --- /dev/null +++ b/src/data/dto/user/user_stats_response.ts @@ -0,0 +1,51 @@ +/** + * 用户统计响应 DTO + */ +import { + UserStatsResponseSchema, + type UserStatsResponseInput, + type UserStatsResponseData, +} from "@/data/schemas/user/user_stats_response"; +import { PersonalityTraits } from "./personality_traits"; +import { RecentMemory } from "./recent_memory"; + +export class UserStatsResponse { + declare readonly userId: string; + declare readonly username: string; + declare readonly platform: string; + declare readonly intimacy: number; + declare readonly relationshipStage: string; + declare readonly dolBalance: number; + declare readonly totalMessages: number; + declare readonly lastMessageAt: string; + declare readonly accountCreatedAt: string; + declare readonly currentMood: string; + declare readonly personalityTraits: PersonalityTraits; + declare readonly recentMemories: RecentMemory[]; + declare readonly promptTokensTotal: number; + declare readonly completionTokensTotal: number; + declare readonly cacheHitTokensTotal: number; + declare readonly tokensTotal: number; + + private constructor(input: UserStatsResponseInput) { + const data = UserStatsResponseSchema.parse(input); + Object.assign(this, { + ...data, + personalityTraits: PersonalityTraits.from(data.personalityTraits), + recentMemories: data.recentMemories.map((m) => RecentMemory.from(m)), + }); + Object.freeze(this); + } + + static from(input: UserStatsResponseInput): UserStatsResponse { + return new UserStatsResponse(input); + } + + static fromJson(json: unknown): UserStatsResponse { + return UserStatsResponse.from(json as UserStatsResponseInput); + } + + toJson(): UserStatsResponseData { + return UserStatsResponseSchema.parse(this); + } +} diff --git a/src/data/models/auth/guest_login_response.ts b/src/data/models/auth/guest_login_response.ts deleted file mode 100644 index 5081e37a..00000000 --- a/src/data/models/auth/guest_login_response.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * 游客登录响应 - * 原始 Dart: GuestLoginResponse (lib/data/models/auth/auth_response.dart) - */ -import { z } from "zod"; -import { User, UserSchema } from "../user/user"; - -export const GuestLoginResponseSchema = z.object({ - token: z.string(), - deviceId: z.string(), - userId: z.string(), - isDeviceUser: z.boolean().default(true), - expiresIn: z.number().default(2592000), - user: UserSchema.optional(), -}); - -export type GuestLoginResponseInput = z.input; -export type GuestLoginResponseData = z.output; - -export class GuestLoginResponse { - declare readonly token: string; - declare readonly deviceId: string; - declare readonly userId: string; - declare readonly isDeviceUser: boolean; - declare readonly expiresIn: number; - declare readonly user: User; - - private constructor(data: GuestLoginResponseData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: GuestLoginResponseInput): GuestLoginResponse { - const parsed = GuestLoginResponseSchema.parse(input); - return new GuestLoginResponse({ - ...parsed, - user: parsed.user ?? User.empty(), - }); - } - - static fromJson(json: unknown): GuestLoginResponse { - return GuestLoginResponse.from(json as GuestLoginResponseInput); - } - - toJson(): GuestLoginResponseData { - const { user, ...rest } = this; - return GuestLoginResponseSchema.parse({ - ...rest, - ...(user.id !== "" ? { user } : {}), - }); - } -} diff --git a/src/data/models/auth/index.ts b/src/data/models/auth/index.ts deleted file mode 100644 index 7ef01db2..00000000 --- a/src/data/models/auth/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from "./apple_login_request"; -export * from "./facebook_login_request"; -export * from "./fb_id_login_request"; -export * from "./google_login_request"; -export * from "./guest_login_request"; -export * from "./guest_login_response"; -export * from "./login_request"; -export * from "./login_response"; -export * from "./logout_response"; -export * from "./refresh_token_request"; -export * from "./refresh_token_response"; -export * from "./register_request"; -export * from "./send_code_request"; diff --git a/src/data/models/chat/index.ts b/src/data/models/chat/index.ts deleted file mode 100644 index b11282a1..00000000 --- a/src/data/models/chat/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @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"; diff --git a/src/data/models/metrics/index.ts b/src/data/models/metrics/index.ts deleted file mode 100644 index 5213df40..00000000 --- a/src/data/models/metrics/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from "./app_event"; -export * from "./pwa_event"; diff --git a/src/data/models/user/avatar_data.ts b/src/data/models/user/avatar_data.ts deleted file mode 100644 index 78addf14..00000000 --- a/src/data/models/user/avatar_data.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 头像数据模型 - 对应后端 AvatarData schema - * 原始 Dart: AvatarData (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const AvatarDataSchema = z.object({ - avatarUrl: z.string().default(""), - userId: z.string(), -}); - -export type AvatarDataInput = z.input; -export type AvatarDataData = z.output; - -export class AvatarData { - declare readonly avatarUrl: string; - declare readonly userId: string; - - private constructor(data: AvatarDataData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: AvatarDataInput): AvatarData { - return new AvatarData(AvatarDataSchema.parse(input)); - } - - static fromJson(json: unknown): AvatarData { - return AvatarData.from(json as AvatarDataInput); - } - - toJson(): AvatarDataData { - return AvatarDataSchema.parse(this); - } -} diff --git a/src/data/models/user/credits_data.ts b/src/data/models/user/credits_data.ts deleted file mode 100644 index f8e3eeee..00000000 --- a/src/data/models/user/credits_data.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 积分数据模型 - 对应后端 CreditsData schema - * 原始 Dart: CreditsData (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const CreditsDataSchema = z.object({ - userId: z.string(), - dolBalance: z.number(), -}); - -export type CreditsDataInput = z.input; -export type CreditsDataData = z.output; - -export class CreditsData { - declare readonly userId: string; - declare readonly dolBalance: number; - - private constructor(data: CreditsDataData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: CreditsDataInput): CreditsData { - return new CreditsData(CreditsDataSchema.parse(input)); - } - - static fromJson(json: unknown): CreditsData { - return CreditsData.from(json as CreditsDataInput); - } - - toJson(): CreditsDataData { - return CreditsDataSchema.parse(this); - } -} diff --git a/src/data/models/user/credits_history_data.ts b/src/data/models/user/credits_history_data.ts deleted file mode 100644 index 62dba106..00000000 --- a/src/data/models/user/credits_history_data.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 积分历史记录模型 - 对应后端 CreditsHistoryData schema - * 原始 Dart: CreditsHistoryData (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const CreditsHistoryDataSchema = z.object({ - records: z.array(z.record(z.string(), z.unknown())), - total: z.number(), - limit: z.number(), - offset: z.number(), -}); - -export type CreditsHistoryDataInput = z.input; -export type CreditsHistoryDataData = z.output; - -export class CreditsHistoryData { - declare readonly records: Record[]; - declare readonly total: number; - declare readonly limit: number; - declare readonly offset: number; - - private constructor(data: CreditsHistoryDataData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: CreditsHistoryDataInput): CreditsHistoryData { - return new CreditsHistoryData(CreditsHistoryDataSchema.parse(input)); - } - - static fromJson(json: unknown): CreditsHistoryData { - return CreditsHistoryData.from(json as CreditsHistoryDataInput); - } - - toJson(): CreditsHistoryDataData { - return CreditsHistoryDataSchema.parse(this); - } -} diff --git a/src/data/models/user/index.ts b/src/data/models/user/index.ts deleted file mode 100644 index 287d1254..00000000 --- a/src/data/models/user/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from "./avatar_data"; -export * from "./credits_data"; -export * from "./credits_history_data"; -export * from "./personality_traits"; -export * from "./recent_memory"; -export * from "./update_profile_request"; -export * from "./user"; -export * from "./user_stats_response"; diff --git a/src/data/models/user/personality_traits.ts b/src/data/models/user/personality_traits.ts deleted file mode 100644 index f9bc397c..00000000 --- a/src/data/models/user/personality_traits.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * 个性特征模型 - * 原始 Dart: PersonalityTraits (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const PERSONALITY_TRAITS_DEFAULTS: PersonalityTraitsData = { - cheerful: 0.5, - caring: 0.5, - playful: 0.5, - serious: 0.5, - romantic: 0.5, -}; - -export const PersonalityTraitsSchema = z.object({ - cheerful: z.number().default(0.5), - caring: z.number().default(0.5), - playful: z.number().default(0.5), - serious: z.number().default(0.5), - romantic: z.number().default(0.5), -}); - -export type PersonalityTraitsInput = z.input; -export type PersonalityTraitsData = z.output; - -export class PersonalityTraits { - declare readonly cheerful: number; - declare readonly caring: number; - declare readonly playful: number; - declare readonly serious: number; - declare readonly romantic: number; - - private constructor(data: PersonalityTraitsData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: PersonalityTraitsInput): PersonalityTraits { - return new PersonalityTraits(PersonalityTraitsSchema.parse(input)); - } - - static fromJson(json: unknown): PersonalityTraits { - return PersonalityTraits.from(json as PersonalityTraitsInput); - } - - toJson(): PersonalityTraitsData { - return PersonalityTraitsSchema.parse(this); - } -} diff --git a/src/data/models/user/recent_memory.ts b/src/data/models/user/recent_memory.ts deleted file mode 100644 index 46f1084b..00000000 --- a/src/data/models/user/recent_memory.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 最近记忆模型 - * 原始 Dart: RecentMemory (lib/data/models/user/recent_memory.dart) - */ -import { z } from "zod"; - -export const RecentMemorySchema = z.object({ - type: z.string(), - content: z.string(), - importance: z.number(), - createdAt: z.string().default(""), -}); - -export type RecentMemoryInput = z.input; -export type RecentMemoryData = z.output; - -export class RecentMemory { - declare readonly type: string; - declare readonly content: string; - declare readonly importance: number; - declare readonly createdAt: string; - - private constructor(data: RecentMemoryData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: RecentMemoryInput): RecentMemory { - return new RecentMemory(RecentMemorySchema.parse(input)); - } - - static fromJson(json: unknown): RecentMemory { - return RecentMemory.from(json as RecentMemoryInput); - } - - toJson(): RecentMemoryData { - return RecentMemorySchema.parse(this); - } -} diff --git a/src/data/models/user/update_profile_request.ts b/src/data/models/user/update_profile_request.ts deleted file mode 100644 index 1b6136e7..00000000 --- a/src/data/models/user/update_profile_request.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 更新个人资料请求 - * 原始 Dart: UpdateProfileRequest (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const UpdateProfileRequestSchema = z.object({ - username: z.string().default(""), - nickname: z.string().default(""), - preferredLanguage: z.string().default(""), - currentMood: z.string().default(""), -}); - -export type UpdateProfileRequestInput = z.input; -export type UpdateProfileRequestData = z.output; - -export class UpdateProfileRequest { - declare readonly username: string; - declare readonly nickname: string; - declare readonly preferredLanguage: string; - declare readonly currentMood: string; - - private constructor(data: UpdateProfileRequestData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: UpdateProfileRequestInput): UpdateProfileRequest { - return new UpdateProfileRequest(UpdateProfileRequestSchema.parse(input)); - } - - static fromJson(json: unknown): UpdateProfileRequest { - return UpdateProfileRequest.from(json as UpdateProfileRequestInput); - } - - toJson(): UpdateProfileRequestData { - return UpdateProfileRequestSchema.parse(this); - } -} diff --git a/src/data/models/user/user.ts b/src/data/models/user/user.ts deleted file mode 100644 index 95066674..00000000 --- a/src/data/models/user/user.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * 用户模型 - 对应后端 UserData schema - * 原始 Dart: User (lib/data/models/user/user.dart) - */ -import { z } from "zod"; -import { - PersonalityTraits, - PersonalityTraitsSchema, - PERSONALITY_TRAITS_DEFAULTS, -} from "./personality_traits"; - -export const UserSchema = z.object({ - id: z.string(), - username: z.string(), - email: z.string().default(""), - platform: z.string().default("web"), - intimacy: z.number().default(0), - dolBalance: z.number().default(0), - relationshipStage: z.string().default("密友"), - currentMood: z.string().default("happy"), - personalityTraits: PersonalityTraitsSchema.default( - PERSONALITY_TRAITS_DEFAULTS - ), - preferredLanguage: z.string().default(""), - createdAt: z.string().default(""), - lastMessageAt: z.string().default(""), - avatarUrl: z.string().default(""), - loginProvider: z.string().default("email"), - isGuest: z.boolean().default(false), -}); - -export type UserInput = z.input; -export type UserData = z.output; - -export class User { - declare readonly id: string; - declare readonly username: string; - declare readonly email: string; - declare readonly platform: string; - declare readonly intimacy: number; - declare readonly dolBalance: number; - declare readonly relationshipStage: string; - declare readonly currentMood: string; - declare readonly personalityTraits: PersonalityTraits; - declare readonly preferredLanguage: string; - declare readonly createdAt: string; - declare readonly lastMessageAt: string; - declare readonly avatarUrl: string; - declare readonly loginProvider: string; - declare readonly isGuest: boolean; - - private constructor(input: UserInput) { - const data = UserSchema.parse(input); - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: UserInput): User { - return new User(input); - } - - static fromJson(json: unknown): User { - return User.from(json as UserInput); - } - - /** - * 创建一个具有空 id/username 的 User 实例,用于可选 user 字段的默认占位。 - * 调用方可通过 `user.id === ""` 判定"无用户数据"。 - */ - static empty(): User { - return new User({ id: "", username: "" }); - } - - toJson(): UserData { - return UserSchema.parse(this); - } -} diff --git a/src/data/models/user/user_stats_response.ts b/src/data/models/user/user_stats_response.ts deleted file mode 100644 index 93b1bb08..00000000 --- a/src/data/models/user/user_stats_response.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * 用户统计响应 - * 原始 Dart: UserStatsResponse (lib/data/models/user/user_stats_response.dart) - */ -import { z } from "zod"; -import { - PersonalityTraits, - PERSONALITY_TRAITS_DEFAULTS, - PersonalityTraitsSchema, -} from "./personality_traits"; -import { RecentMemory, RecentMemorySchema } from "./recent_memory"; - -export const UserStatsResponseSchema = z.object({ - userId: z.string(), - username: z.string(), - platform: z.string(), - intimacy: z.number(), - relationshipStage: z.string(), - dolBalance: z.number(), - totalMessages: z.number(), - lastMessageAt: z.string().default(""), - accountCreatedAt: z.string().default(""), - currentMood: z.string().default(""), - personalityTraits: PersonalityTraitsSchema.default( - PERSONALITY_TRAITS_DEFAULTS - ), - recentMemories: z.array(RecentMemorySchema).default([]), - promptTokensTotal: z.number().default(0), - completionTokensTotal: z.number().default(0), - cacheHitTokensTotal: z.number().default(0), - tokensTotal: z.number().default(0), -}); - -export type UserStatsResponseInput = z.input; -export type UserStatsResponseData = z.output; - -export class UserStatsResponse { - declare readonly userId: string; - declare readonly username: string; - declare readonly platform: string; - declare readonly intimacy: number; - declare readonly relationshipStage: string; - declare readonly dolBalance: number; - declare readonly totalMessages: number; - declare readonly lastMessageAt: string; - declare readonly accountCreatedAt: string; - declare readonly currentMood: string; - declare readonly personalityTraits: PersonalityTraits; - declare readonly recentMemories: RecentMemory[]; - declare readonly promptTokensTotal: number; - declare readonly completionTokensTotal: number; - declare readonly cacheHitTokensTotal: number; - declare readonly tokensTotal: number; - - private constructor(data: UserStatsResponseData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: UserStatsResponseInput): UserStatsResponse { - return new UserStatsResponse(UserStatsResponseSchema.parse(input)); - } - - static fromJson(json: unknown): UserStatsResponse { - return UserStatsResponse.from(json as UserStatsResponseInput); - } - - toJson(): UserStatsResponseData { - return UserStatsResponseSchema.parse(this); - } -} diff --git a/src/data/schemas/auth/apple_login_request.ts b/src/data/schemas/auth/apple_login_request.ts new file mode 100644 index 00000000..09da28e1 --- /dev/null +++ b/src/data/schemas/auth/apple_login_request.ts @@ -0,0 +1,13 @@ +/** + * Apple 登录请求 + * 原始 Dart: AppleLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const AppleLoginRequestSchema = z.object({ + identityToken: z.string(), + platform: z.string(), +}); + +export type AppleLoginRequestInput = z.input; +export type AppleLoginRequestData = z.output; diff --git a/src/data/schemas/auth/facebook_login_request.ts b/src/data/schemas/auth/facebook_login_request.ts new file mode 100644 index 00000000..074014ac --- /dev/null +++ b/src/data/schemas/auth/facebook_login_request.ts @@ -0,0 +1,14 @@ +/** + * Facebook 登录请求 + * 原始 Dart: FacebookLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const FacebookLoginRequestSchema = z.object({ + accessToken: z.string(), + platform: z.string(), + guestId: z.string().default(""), +}); + +export type FacebookLoginRequestInput = z.input; +export type FacebookLoginRequestData = z.output; diff --git a/src/data/schemas/auth/fb_id_login_request.ts b/src/data/schemas/auth/fb_id_login_request.ts new file mode 100644 index 00000000..d9207346 --- /dev/null +++ b/src/data/schemas/auth/fb_id_login_request.ts @@ -0,0 +1,13 @@ +/** + * Facebook ID 登录请求 + * 原始 Dart: FbIdLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const FbIdLoginRequestSchema = z.object({ + fbId: z.string(), + avatarUrl: z.string().default(""), +}); + +export type FbIdLoginRequestInput = z.input; +export type FbIdLoginRequestData = z.output; diff --git a/src/data/schemas/auth/google_login_request.ts b/src/data/schemas/auth/google_login_request.ts new file mode 100644 index 00000000..d39cd0dd --- /dev/null +++ b/src/data/schemas/auth/google_login_request.ts @@ -0,0 +1,14 @@ +/** + * Google 登录请求 + * 原始 Dart: GoogleLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const GoogleLoginRequestSchema = z.object({ + idToken: z.string(), + platform: z.string(), + guestId: z.string().default(""), +}); + +export type GoogleLoginRequestInput = z.input; +export type GoogleLoginRequestData = z.output; diff --git a/src/data/schemas/auth/guest_login_request.ts b/src/data/schemas/auth/guest_login_request.ts new file mode 100644 index 00000000..09bba9d9 --- /dev/null +++ b/src/data/schemas/auth/guest_login_request.ts @@ -0,0 +1,12 @@ +/** + * 游客登录请求 + * 原始 Dart: GuestLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const GuestLoginRequestSchema = z.object({ + deviceId: z.string(), +}); + +export type GuestLoginRequestInput = z.input; +export type GuestLoginRequestData = z.output; diff --git a/src/data/schemas/auth/guest_login_response.ts b/src/data/schemas/auth/guest_login_response.ts new file mode 100644 index 00000000..86e67eb1 --- /dev/null +++ b/src/data/schemas/auth/guest_login_response.ts @@ -0,0 +1,18 @@ +/** + * 游客登录响应 + * 原始 Dart: GuestLoginResponse (lib/data/models/auth/auth_response.dart) + */ +import { z } from "zod"; +import { UserSchema } from "../user/user"; + +export const GuestLoginResponseSchema = z.object({ + token: z.string(), + deviceId: z.string(), + userId: z.string(), + isDeviceUser: z.boolean().default(true), + expiresIn: z.number().default(2592000), + user: UserSchema.optional(), +}); + +export type GuestLoginResponseInput = z.input; +export type GuestLoginResponseData = z.output; diff --git a/src/data/schemas/auth/login_request.ts b/src/data/schemas/auth/login_request.ts new file mode 100644 index 00000000..bcea9aa6 --- /dev/null +++ b/src/data/schemas/auth/login_request.ts @@ -0,0 +1,16 @@ +/** + * 登录请求 + * 原始 Dart: LoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const LoginRequestSchema = z.object({ + email: z.string().default(""), + username: z.string().default(""), + password: z.string(), + platform: z.string(), + guestId: z.string().default(""), +}); + +export type LoginRequestInput = z.input; +export type LoginRequestData = z.output; diff --git a/src/data/schemas/auth/login_response.ts b/src/data/schemas/auth/login_response.ts new file mode 100644 index 00000000..c7f31063 --- /dev/null +++ b/src/data/schemas/auth/login_response.ts @@ -0,0 +1,15 @@ +/** + * 登录响应 + * 原始 Dart: LoginResponse (lib/data/models/auth/auth_response.dart) + */ +import { z } from "zod"; +import { UserSchema } from "../user/user"; + +export const LoginResponseSchema = z.object({ + user: UserSchema, + token: z.string(), + refreshToken: z.string().default(""), +}); + +export type LoginResponseInput = z.input; +export type LoginResponseData = z.output; diff --git a/src/data/schemas/auth/logout_response.ts b/src/data/schemas/auth/logout_response.ts new file mode 100644 index 00000000..01f4d2d6 --- /dev/null +++ b/src/data/schemas/auth/logout_response.ts @@ -0,0 +1,12 @@ +/** + * 退出登录响应 + * 原始 Dart: LogoutResponse (lib/data/models/auth/auth_response.dart) + */ +import { z } from "zod"; + +export const LogoutResponseSchema = z.object({ + success: z.boolean().default(true), +}); + +export type LogoutResponseInput = z.input; +export type LogoutResponseData = z.output; diff --git a/src/data/schemas/auth/refresh_token_request.ts b/src/data/schemas/auth/refresh_token_request.ts new file mode 100644 index 00000000..4db3e522 --- /dev/null +++ b/src/data/schemas/auth/refresh_token_request.ts @@ -0,0 +1,12 @@ +/** + * 刷新 Token 请求 + * 原始 Dart: RefreshTokenRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const RefreshTokenRequestSchema = z.object({ + refreshToken: z.string(), +}); + +export type RefreshTokenRequestInput = z.input; +export type RefreshTokenRequestData = z.output; diff --git a/src/data/schemas/auth/refresh_token_response.ts b/src/data/schemas/auth/refresh_token_response.ts new file mode 100644 index 00000000..d0a6fe5c --- /dev/null +++ b/src/data/schemas/auth/refresh_token_response.ts @@ -0,0 +1,14 @@ +/** + * 刷新 Token 响应 + * 原始 Dart: RefreshTokenResponse (lib/data/models/auth/auth_response.dart) + */ +import { z } from "zod"; + +export const RefreshTokenResponseSchema = z.object({ + token: z.string(), + refreshToken: z.string(), + userId: z.string(), +}); + +export type RefreshTokenResponseInput = z.input; +export type RefreshTokenResponseData = z.output; diff --git a/src/data/schemas/auth/register_request.ts b/src/data/schemas/auth/register_request.ts new file mode 100644 index 00000000..7ed90574 --- /dev/null +++ b/src/data/schemas/auth/register_request.ts @@ -0,0 +1,16 @@ +/** + * 注册请求 + * 原始 Dart: RegisterRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const RegisterRequestSchema = z.object({ + username: z.string(), + email: z.string(), + password: z.string(), + platform: z.string(), + guestId: z.string().default(""), +}); + +export type RegisterRequestInput = z.input; +export type RegisterRequestData = z.output; diff --git a/src/data/schemas/auth/send_code_request.ts b/src/data/schemas/auth/send_code_request.ts new file mode 100644 index 00000000..9ff3b115 --- /dev/null +++ b/src/data/schemas/auth/send_code_request.ts @@ -0,0 +1,12 @@ +/** + * 发送验证码请求 + * 原始 Dart: SendCodeRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const SendCodeRequestSchema = z.object({ + email: z.string(), +}); + +export type SendCodeRequestInput = z.input; +export type SendCodeRequestData = z.output; diff --git a/src/data/schemas/chat/chat_history_response.ts b/src/data/schemas/chat/chat_history_response.ts new file mode 100644 index 00000000..824405be --- /dev/null +++ b/src/data/schemas/chat/chat_history_response.ts @@ -0,0 +1,16 @@ +/** + * 聊天历史响应 + * 原始 Dart: ChatHistoryResponse (lib/data/models/chat/chat_response.dart) + */ +import { z } from "zod"; +import { ChatMessageSchema } from "./chat_message"; + +export const ChatHistoryResponseSchema = z.object({ + messages: z.array(ChatMessageSchema), + total: z.number().default(0), + limit: z.number(), + offset: z.number(), +}); + +export type ChatHistoryResponseInput = z.input; +export type ChatHistoryResponseData = z.output; diff --git a/src/data/schemas/chat/chat_message.ts b/src/data/schemas/chat/chat_message.ts new file mode 100644 index 00000000..3e4ab1b6 --- /dev/null +++ b/src/data/schemas/chat/chat_message.ts @@ -0,0 +1,15 @@ +/** + * 聊天历史中的单条消息 + * 原始 Dart: ChatMessage (lib/data/models/chat/chat_response.dart) + */ +import { z } from "zod"; + +export const ChatMessageSchema = z.object({ + role: z.string(), + content: z.string(), + id: z.string().default(""), + createdAt: z.string().default(""), +}); + +export type ChatMessageInput = z.input; +export type ChatMessageData = z.output; diff --git a/src/data/schemas/chat/chat_send_response.ts b/src/data/schemas/chat/chat_send_response.ts new file mode 100644 index 00000000..74dd4550 --- /dev/null +++ b/src/data/schemas/chat/chat_send_response.ts @@ -0,0 +1,22 @@ +/** + * 发送消息响应 + * 原始 Dart: ChatSendResponse (lib/data/models/chat/chat_response.dart) + */ +import { z } from "zod"; + +export const ChatSendResponseSchema = z.object({ + mode: z.string().default(""), + reply: z.string(), + voiceUrl: z.string().default(""), + audioUrl: z.string().default(""), + intimacyChange: z.number().default(0), + newIntimacy: z.number().default(0), + relationshipStage: z.string(), + currentMood: z.string().default(""), + messageId: z.string(), + isGuest: z.boolean().default(false), + timestamp: z.number().default(0), +}); + +export type ChatSendResponseInput = z.input; +export type ChatSendResponseData = z.output; diff --git a/src/data/schemas/chat/chat_sync_data.ts b/src/data/schemas/chat/chat_sync_data.ts new file mode 100644 index 00000000..a541880e --- /dev/null +++ b/src/data/schemas/chat/chat_sync_data.ts @@ -0,0 +1,13 @@ +/** + * 消息同步响应 + * 原始 Dart: ChatSyncData (lib/data/models/chat/chat_sync.dart) + */ +import { z } from "zod"; + +export const ChatSyncDataSchema = z.object({ + syncedCount: z.number(), + totalHistory: z.number(), +}); + +export type ChatSyncDataInput = z.input; +export type ChatSyncDataData = z.output; diff --git a/src/data/schemas/chat/chat_sync_request.ts b/src/data/schemas/chat/chat_sync_request.ts new file mode 100644 index 00000000..2995a544 --- /dev/null +++ b/src/data/schemas/chat/chat_sync_request.ts @@ -0,0 +1,13 @@ +/** + * 消息同步请求 + * 原始 Dart: ChatSyncRequest (lib/data/models/chat/chat_sync.dart) + */ +import { z } from "zod"; +import { SyncMessageSchema } from "./sync_message"; + +export const ChatSyncRequestSchema = z.object({ + messages: z.array(SyncMessageSchema), +}); + +export type ChatSyncRequestInput = z.input; +export type ChatSyncRequestData = z.output; diff --git a/src/data/schemas/chat/guest_chat_quota.ts b/src/data/schemas/chat/guest_chat_quota.ts new file mode 100644 index 00000000..0d6c4450 --- /dev/null +++ b/src/data/schemas/chat/guest_chat_quota.ts @@ -0,0 +1,13 @@ +/** + * 游客每日聊天配额数据 + * 原始 Dart: GuestChatQuota (lib/data/models/chat/guest_chat_quota.dart) + */ +import { z } from "zod"; + +export const GuestChatQuotaSchema = z.object({ + remaining: z.number(), + date: z.string(), +}); + +export type GuestChatQuotaInput = z.input; +export type GuestChatQuotaData = z.output; diff --git a/src/data/schemas/chat/image_upload_response.ts b/src/data/schemas/chat/image_upload_response.ts new file mode 100644 index 00000000..569734c7 --- /dev/null +++ b/src/data/schemas/chat/image_upload_response.ts @@ -0,0 +1,19 @@ +/** + * 图片上传响应 + * 原始 Dart: ImageUploadResponse (lib/data/models/chat/image_upload_response.dart) + */ +import { z } from "zod"; + +export const ImageUploadResponseSchema = z.object({ + success: z.boolean().default(true), + imageId: z.string(), + thumbUrl: z.string(), + mediumUrl: z.string(), + originalUrl: z.string(), + width: z.number(), + height: z.number(), + bytes: z.number(), +}); + +export type ImageUploadResponseInput = z.input; +export type ImageUploadResponseData = z.output; diff --git a/src/data/schemas/chat/send_message_request.ts b/src/data/schemas/chat/send_message_request.ts new file mode 100644 index 00000000..445f065e --- /dev/null +++ b/src/data/schemas/chat/send_message_request.ts @@ -0,0 +1,20 @@ +/** + * 发送消息请求 + * 原始 Dart: SendMessageRequest (lib/data/models/chat/send_message_request.dart) + */ +import { z } from "zod"; + +export const SendMessageRequestSchema = z.object({ + message: z.string().default(""), + image: z.string().default(""), + imageId: z.string().default(""), + imageThumbUrl: z.string().default(""), + imageMediumUrl: z.string().default(""), + imageOriginalUrl: z.string().default(""), + imageWidth: z.number().default(0), + imageHeight: z.number().default(0), + useWebSocket: z.boolean().default(false), +}); + +export type SendMessageRequestInput = z.input; +export type SendMessageRequestData = z.output; diff --git a/src/data/schemas/chat/stt_data.ts b/src/data/schemas/chat/stt_data.ts new file mode 100644 index 00000000..75a3315f --- /dev/null +++ b/src/data/schemas/chat/stt_data.ts @@ -0,0 +1,12 @@ +/** + * STT(语音转文字)响应 + * 原始 Dart: SttData (lib/data/models/chat/stt_response.dart) + */ +import { z } from "zod"; + +export const SttDataSchema = z.object({ + text: z.string(), +}); + +export type SttDataInput = z.input; +export type SttDataData = z.output; diff --git a/src/data/schemas/chat/sync_message.ts b/src/data/schemas/chat/sync_message.ts new file mode 100644 index 00000000..cd05666b --- /dev/null +++ b/src/data/schemas/chat/sync_message.ts @@ -0,0 +1,14 @@ +/** + * 待同步的单条消息 + * 原始 Dart: SyncMessage (lib/data/models/chat/chat_sync.dart) + */ +import { z } from "zod"; + +export const SyncMessageSchema = z.object({ + role: z.string(), + content: z.string(), + timestamp: z.string(), +}); + +export type SyncMessageInput = z.input; +export type SyncMessageData = z.output; diff --git a/src/data/schemas/index.ts b/src/data/schemas/index.ts new file mode 100644 index 00000000..3a07cd5d --- /dev/null +++ b/src/data/schemas/index.ts @@ -0,0 +1,42 @@ +/** + * Schemas - 集中导出 + * + * Zod schema + 类型(Source of Truth) + * 原始 Dart: lib/data/models/ + */ +export * from "./auth/apple_login_request"; +export * from "./auth/facebook_login_request"; +export * from "./auth/fb_id_login_request"; +export * from "./auth/google_login_request"; +export * from "./auth/guest_login_request"; +export * from "./auth/guest_login_response"; +export * from "./auth/login_request"; +export * from "./auth/login_response"; +export * from "./auth/logout_response"; +export * from "./auth/refresh_token_request"; +export * from "./auth/refresh_token_response"; +export * from "./auth/register_request"; +export * from "./auth/send_code_request"; + +export * from "./chat/chat_history_response"; +export * from "./chat/chat_message"; +export * from "./chat/chat_send_response"; +export * from "./chat/chat_sync_data"; +export * from "./chat/chat_sync_request"; +export * from "./chat/guest_chat_quota"; +export * from "./chat/image_upload_response"; +export * from "./chat/send_message_request"; +export * from "./chat/stt_data"; +export * from "./chat/sync_message"; + +export * from "./metrics/app_event"; +export * from "./metrics/pwa_event"; + +export * from "./user/avatar_data"; +export * from "./user/credits_data"; +export * from "./user/credits_history_data"; +export * from "./user/personality_traits"; +export * from "./user/recent_memory"; +export * from "./user/update_profile_request"; +export * from "./user/user"; +export * from "./user/user_stats_response"; diff --git a/src/data/schemas/metrics/app_event.ts b/src/data/schemas/metrics/app_event.ts new file mode 100644 index 00000000..1dd832c9 --- /dev/null +++ b/src/data/schemas/metrics/app_event.ts @@ -0,0 +1,14 @@ +/** + * 应用事件上报请求 + * 原始 Dart: AppEvent (lib/data/models/metrics/app_event.dart) + */ +import { z } from "zod"; + +export const AppEventSchema = z.object({ + userId: z.string(), + browser: z.string(), + userAgent: z.string(), +}); + +export type AppEventInput = z.input; +export type AppEventData = z.output; diff --git a/src/data/schemas/metrics/pwa_event.ts b/src/data/schemas/metrics/pwa_event.ts new file mode 100644 index 00000000..56c80d1a --- /dev/null +++ b/src/data/schemas/metrics/pwa_event.ts @@ -0,0 +1,16 @@ +/** + * PWA 事件上报请求 + * 原始 Dart: PwaEvent (lib/data/models/metrics/pwa_event.dart) + */ +import { z } from "zod"; + +export const PwaEventSchema = z.object({ + deviceId: z.string(), + deviceType: z.string(), + timestamp: z.number(), + pwaInstalled: z.boolean().default(false), + pwaSupported: z.boolean().default(false), +}); + +export type PwaEventInput = z.input; +export type PwaEventData = z.output; diff --git a/src/data/schemas/user/avatar_data.ts b/src/data/schemas/user/avatar_data.ts new file mode 100644 index 00000000..a985c8c4 --- /dev/null +++ b/src/data/schemas/user/avatar_data.ts @@ -0,0 +1,13 @@ +/** + * 头像数据模型 + * 原始 Dart: AvatarData (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const AvatarDataSchema = z.object({ + avatarUrl: z.string().default(""), + userId: z.string(), +}); + +export type AvatarDataInput = z.input; +export type AvatarDataData = z.output; diff --git a/src/data/schemas/user/credits_data.ts b/src/data/schemas/user/credits_data.ts new file mode 100644 index 00000000..aae7a373 --- /dev/null +++ b/src/data/schemas/user/credits_data.ts @@ -0,0 +1,13 @@ +/** + * 积分数据模型 + * 原始 Dart: CreditsData (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const CreditsDataSchema = z.object({ + userId: z.string(), + dolBalance: z.number(), +}); + +export type CreditsDataInput = z.input; +export type CreditsDataData = z.output; diff --git a/src/data/schemas/user/credits_history_data.ts b/src/data/schemas/user/credits_history_data.ts new file mode 100644 index 00000000..0b531479 --- /dev/null +++ b/src/data/schemas/user/credits_history_data.ts @@ -0,0 +1,15 @@ +/** + * 积分历史记录模型 + * 原始 Dart: CreditsHistoryData (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const CreditsHistoryDataSchema = z.object({ + records: z.array(z.record(z.string(), z.unknown())), + total: z.number(), + limit: z.number(), + offset: z.number(), +}); + +export type CreditsHistoryDataInput = z.input; +export type CreditsHistoryDataData = z.output; diff --git a/src/data/schemas/user/personality_traits.ts b/src/data/schemas/user/personality_traits.ts new file mode 100644 index 00000000..73799c35 --- /dev/null +++ b/src/data/schemas/user/personality_traits.ts @@ -0,0 +1,24 @@ +/** + * 个性特征模型 + * 原始 Dart: PersonalityTraits (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const PERSONALITY_TRAITS_DEFAULTS = { + cheerful: 0.5, + caring: 0.5, + playful: 0.5, + serious: 0.5, + romantic: 0.5, +} as const; + +export const PersonalityTraitsSchema = z.object({ + cheerful: z.number().default(0.5), + caring: z.number().default(0.5), + playful: z.number().default(0.5), + serious: z.number().default(0.5), + romantic: z.number().default(0.5), +}); + +export type PersonalityTraitsInput = z.input; +export type PersonalityTraitsData = z.output; diff --git a/src/data/schemas/user/recent_memory.ts b/src/data/schemas/user/recent_memory.ts new file mode 100644 index 00000000..2b052a1a --- /dev/null +++ b/src/data/schemas/user/recent_memory.ts @@ -0,0 +1,15 @@ +/** + * 最近记忆模型 + * 原始 Dart: RecentMemory (lib/data/models/user/recent_memory.dart) + */ +import { z } from "zod"; + +export const RecentMemorySchema = z.object({ + type: z.string(), + content: z.string(), + importance: z.number(), + createdAt: z.string().default(""), +}); + +export type RecentMemoryInput = z.input; +export type RecentMemoryData = z.output; diff --git a/src/data/schemas/user/update_profile_request.ts b/src/data/schemas/user/update_profile_request.ts new file mode 100644 index 00000000..574c55a3 --- /dev/null +++ b/src/data/schemas/user/update_profile_request.ts @@ -0,0 +1,15 @@ +/** + * 更新个人资料请求 + * 原始 Dart: UpdateProfileRequest (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const UpdateProfileRequestSchema = z.object({ + username: z.string().default(""), + nickname: z.string().default(""), + preferredLanguage: z.string().default(""), + currentMood: z.string().default(""), +}); + +export type UpdateProfileRequestInput = z.input; +export type UpdateProfileRequestData = z.output; diff --git a/src/data/schemas/user/user.ts b/src/data/schemas/user/user.ts new file mode 100644 index 00000000..2294cecc --- /dev/null +++ b/src/data/schemas/user/user.ts @@ -0,0 +1,27 @@ +/** + * 用户模型 + * 原始 Dart: User (lib/data/models/user/user.dart) + */ +import { z } from "zod"; +import { PersonalityTraitsSchema, PERSONALITY_TRAITS_DEFAULTS } from "./personality_traits"; + +export const UserSchema = z.object({ + id: z.string(), + username: z.string(), + email: z.string().default(""), + platform: z.string().default("web"), + intimacy: z.number().default(0), + dolBalance: z.number().default(0), + relationshipStage: z.string().default("密友"), + currentMood: z.string().default("happy"), + personalityTraits: PersonalityTraitsSchema.default(PERSONALITY_TRAITS_DEFAULTS), + preferredLanguage: z.string().default(""), + createdAt: z.string().default(""), + lastMessageAt: z.string().default(""), + avatarUrl: z.string().default(""), + loginProvider: z.string().default("email"), + isGuest: z.boolean().default(false), +}); + +export type UserInput = z.input; +export type UserData = z.output; diff --git a/src/data/schemas/user/user_stats_response.ts b/src/data/schemas/user/user_stats_response.ts new file mode 100644 index 00000000..0fb987c2 --- /dev/null +++ b/src/data/schemas/user/user_stats_response.ts @@ -0,0 +1,29 @@ +/** + * 用户统计响应 + * 原始 Dart: UserStatsResponse (lib/data/models/user/user_stats_response.dart) + */ +import { z } from "zod"; +import { PersonalityTraitsSchema, PERSONALITY_TRAITS_DEFAULTS } from "./personality_traits"; +import { RecentMemorySchema } from "./recent_memory"; + +export const UserStatsResponseSchema = z.object({ + userId: z.string(), + username: z.string(), + platform: z.string(), + intimacy: z.number(), + relationshipStage: z.string(), + dolBalance: z.number(), + totalMessages: z.number(), + lastMessageAt: z.string().default(""), + accountCreatedAt: z.string().default(""), + currentMood: z.string().default(""), + personalityTraits: PersonalityTraitsSchema.default(PERSONALITY_TRAITS_DEFAULTS), + recentMemories: z.array(RecentMemorySchema).default([]), + promptTokensTotal: z.number().default(0), + completionTokensTotal: z.number().default(0), + cacheHitTokensTotal: z.number().default(0), + tokensTotal: z.number().default(0), +}); + +export type UserStatsResponseInput = z.input; +export type UserStatsResponseData = z.output; diff --git a/src/data/storage/chat/chat_storage.ts b/src/data/storage/chat/chat_storage.ts index b908c960..11da3eed 100644 --- a/src/data/storage/chat/chat_storage.ts +++ b/src/data/storage/chat/chat_storage.ts @@ -18,7 +18,7 @@ import { GuestChatQuotaSchema, type GuestChatQuotaData, -} from "@/data/models"; +} from "@/data/schemas/chat/guest_chat_quota"; import { z } from "zod"; import { LocalStorage } from "../local_storage"; diff --git a/src/data/storage/chat/ichat_storage.ts b/src/data/storage/chat/ichat_storage.ts index 322bb906..589c2f98 100644 --- a/src/data/storage/chat/ichat_storage.ts +++ b/src/data/storage/chat/ichat_storage.ts @@ -6,13 +6,13 @@ * 对齐 Dart 端 `IChatStorage`(lib/data/services/storage/chat/ichat_storage.dart): * - 游客每日聊天配额 + 游客总配额 两个独立字段的 CRUD * - * 注:`GuestChatQuota` 模型见 `src/data/models/chat/guest_chat_quota.ts`, + * 注:`GuestChatQuota` 模型见 `src/data/dto/chat/guest_chat_quota.ts`, * 数据形态 `{ remaining: number, date: string }`。 * 跨天重置逻辑(`needsReset`)保留在 `GuestChatQuota` 类上,存储层只做读写。 */ import type { Result } from "../result"; -import type { GuestChatQuotaData } from "@/data/models"; +import type { GuestChatQuotaData } from "@/data/schemas/chat/guest_chat_quota"; export interface IChatStorage { getGuestDailyChatQuota(): Promise>; diff --git a/src/data/storage/user/iuser_storage.ts b/src/data/storage/user/iuser_storage.ts index a80ac719..2c6a1103 100644 --- a/src/data/storage/user/iuser_storage.ts +++ b/src/data/storage/user/iuser_storage.ts @@ -7,12 +7,12 @@ * - User 对象 / userId / avatarUrl 三个独立字段的 CRUD * - `clearUserData()` 批量清空 * - * 注:完整 User 模型见 `src/data/models/user/user.ts`,本接口允许存 JSON 字符串, + * 注:完整 User 模型见 `src/data/dto/user/user.ts`,本接口允许存 JSON 字符串, * 具体序列化由实现层通过 Zod schema 校验后转换为 `User` 类实例。 */ import type { Result } from "../result"; -import type { UserData } from "@/data/models"; +import type { UserData } from "@/data/schemas/user/user"; export interface IUserStorage { getUser(): Promise>; diff --git a/src/data/storage/user/user_storage.ts b/src/data/storage/user/user_storage.ts index 431c94e6..52d15558 100644 --- a/src/data/storage/user/user_storage.ts +++ b/src/data/storage/user/user_storage.ts @@ -15,7 +15,7 @@ * - 单例挂在 class 静态字段,HMR 复用安全 */ -import { UserSchema, type UserData } from "@/data/models"; +import { UserSchema, type UserData } from "@/data/schemas/user/user"; import { LocalStorage } from "../local_storage"; import { type Result as ResultT } from "../result"; import { StorageKeys } from "../storage_keys";