refactor(dto): move app models into dto layer

This commit is contained in:
2026-06-17 17:34:55 +08:00
parent f0b5275c55
commit 5d66cef85c
24 changed files with 30 additions and 41 deletions
+11
View File
@@ -0,0 +1,11 @@
/**
* 认证模式(登录 / 注册)
*
* 原始 Dart: lib/ui/auth/model/auth_mode.dart
*/
export const AuthMode = {
Login: "login",
Register: "register",
} as const;
export type AuthMode = (typeof AuthMode)[keyof typeof AuthMode];
+12
View File
@@ -0,0 +1,12 @@
/**
* 认证面板模式(Facebook / Email
*
* 原始 Dart: lib/ui/auth/model/auth_panel_mode.dart
*/
export const AuthPanelMode = {
Facebook: "facebook",
Email: "email",
} as const;
export type AuthPanelMode =
(typeof AuthPanelMode)[keyof typeof AuthPanelMode];
+3
View File
@@ -3,12 +3,15 @@
*/
export * from "./apple_login_request";
export * from "./auth_mode";
export * from "./auth_panel_mode";
export * from "./facebook_login_request";
export * from "./facebook_user_data";
export * from "./fb_id_login_request";
export * from "./google_login_request";
export * from "./guest_login_request";
export * from "./guest_login_response";
export * from "./login_status";
export * from "./login_request";
export * from "./login_response";
export * from "./logout_response";
+19
View File
@@ -0,0 +1,19 @@
/**
* 登录状态枚举
*/
export const LoginStatus = {
/** 未登录(默认初值) */
NotLoggedIn: "notLoggedIn",
/** 游客登录 */
Guest: "guest",
/** Facebook OAuth 登录 */
Facebook: "facebook",
/** Google OAuth 登录 */
Google: "google",
/** 邮箱 + 密码登录 */
Email: "email",
/** Apple ID 登录 */
Apple: "apple",
} as const;
export type LoginStatus = (typeof LoginStatus)[keyof typeof LoginStatus];
+28
View File
@@ -0,0 +1,28 @@
/**
* 聊天列表项 discriminated union
*
* 原始 Dart: lib/ui/chat/models/chat_list_item.dart
*
* 4 种类型:
* - ai-disclosure:顶部 AI 披露横幅
* - date-separator:日期分隔条
* - loading-animationAI 正在输入的动画
* - message:实际消息
*/
import type { UiMessage } from "./ui_message";
export type ChatListItem =
| { type: "ai-disclosure" }
| { type: "date-separator"; date: string }
| { type: "loading-animation" }
| { type: "message"; message: UiMessage; key: string };
export const ChatListItemType = {
AiDisclosure: "ai-disclosure",
DateSeparator: "date-separator",
LoadingAnimation: "loading-animation",
Message: "message",
} as const;
export type ChatListItemType =
(typeof ChatListItemType)[keyof typeof ChatListItemType];
+2
View File
@@ -3,6 +3,7 @@
*/
export * from "./chat_history_response";
export * from "./chat_list_item";
export * from "./chat_message";
export * from "./chat_send_response";
export * from "./chat_sync_data";
@@ -12,3 +13,4 @@ export * from "./image_upload_response";
export * from "./send_message_request";
export * from "./stt_data";
export * from "./sync_message";
export * from "./ui_message";
+36
View File
@@ -0,0 +1,36 @@
/**
* 聊天 UI 消息模型
*
* 原始 Dart: lib/ui/chat/models/message.dartfreezed + json_serializable 生成)
*
* 字段:content、isFromAI、date、imageUrl(可选)、voiceUrl(可选)
*/
import { z } from "zod";
export const UiMessageSchema = z.object({
content: z.string(),
isFromAI: z.boolean(),
/** 显示用时间戳(HH:mm */
date: z.string(),
/** 图片 URLbase64 data URL 或 http URL */
imageUrl: z.string().optional(),
/** 语音 URL */
voiceUrl: z.string().optional(),
});
export type UiMessage = z.infer<typeof UiMessageSchema>;
/** 工厂函数(替代 Dart `UiMessage(content:..., isFromAI:...)` 构造)。 */
export const UiMessage = {
create(input: Omit<UiMessage, "date"> & { date?: string }): UiMessage {
return UiMessageSchema.parse({
...input,
date:
input.date ??
new Date().toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
}),
});
},
};
+1
View File
@@ -10,3 +10,4 @@ export * from "./recent_memory";
export * from "./update_profile_request";
export * from "./user";
export * from "./user_stats_response";
export * from "./user_view";
+23
View File
@@ -0,0 +1,23 @@
/**
* UI 侧用户模型(基于 data/dto/user/user + user_storage 重新导出 view-model
*
* 原始 Dart: lib/data/models/user/user.dart
*/
import { z } from "zod";
export const UserViewSchema = z.object({
id: z.string(),
username: z.string(),
email: z.string(),
avatarUrl: z.string(),
intimacy: z.number(),
dolBalance: z.number(),
relationshipStage: z.string(),
currentMood: z.string(),
isGuest: z.boolean(),
isVip: z.boolean(),
voiceMinutesRemaining: z.number(),
stripeCustomerId: z.string().nullable(),
});
export type UserView = z.infer<typeof UserViewSchema>;