feat(chat): migrate chat protocol to lock detail

This commit is contained in:
2026-06-24 14:06:30 +08:00
parent c280a3c1ea
commit 42c03f8901
34 changed files with 609 additions and 373 deletions
+1 -1
View File
@@ -14,5 +14,5 @@ export class ChatStorage {
}
// 本地游客消息数量额度逻辑已停用:
// 游客 / 非游客的消息数量限制统一由后端接口返回 blocked/daily_limit。
// 游客 / 非游客的消息数量限制统一由后端接口返回 lockDetail/daily_limit。
}
+8 -4
View File
@@ -12,6 +12,10 @@
*/
import Dexie, { type Table } from "dexie";
import type {
ChatImageData,
ChatLockDetailData,
} from "@/data/schemas/chat";
export interface LocalMessageRow {
/** Dexie 自增主键(数据库内部使用,不暴露给 LocalMessage 类)。 */
@@ -19,12 +23,12 @@ export interface LocalMessageRow {
/** 消息 id(来自 ChatMessage.id)。 */
id: string;
role: string;
type: string;
content: string;
createdAt: string;
imageUrl?: string | null;
isPrivate?: boolean | null;
privateLocked?: boolean | null;
privateHint?: string | null;
audioUrl?: string | null;
image?: ChatImageData;
lockDetail?: ChatLockDetailData;
sessionId: string;
}
+17 -16
View File
@@ -15,17 +15,18 @@
*/
import { z } from "zod";
import { ChatImageSchema, ChatLockDetailSchema } from "@/data/schemas/chat";
import type { LocalMessageRow } from "./local_chat_db";
export const LocalMessageSchema = z.object({
id: z.string(),
role: z.string(),
type: z.string().default("text"),
content: z.string(),
createdAt: z.string().default(""),
imageUrl: z.string().nullable().default(null),
isPrivate: z.boolean().nullable().default(null),
privateLocked: z.boolean().nullable().default(null),
privateHint: z.string().nullable().default(null),
audioUrl: z.string().nullable().default(null),
image: ChatImageSchema,
lockDetail: ChatLockDetailSchema,
sessionId: z.string().default(""),
});
@@ -35,12 +36,12 @@ export type LocalMessageData = z.output<typeof LocalMessageSchema>;
export class LocalMessage {
declare readonly id: string;
declare readonly role: string;
declare readonly type: string;
declare readonly content: string;
declare readonly createdAt: string;
declare readonly imageUrl: string | null;
declare readonly isPrivate: boolean | null;
declare readonly privateLocked: boolean | null;
declare readonly privateHint: string | null;
declare readonly audioUrl: string | null;
declare readonly image: z.output<typeof ChatImageSchema>;
declare readonly lockDetail: z.output<typeof ChatLockDetailSchema>;
declare readonly sessionId: string;
private constructor(input: LocalMessageInput) {
@@ -66,12 +67,12 @@ export class LocalMessage {
return {
id: this.id,
role: this.role,
type: this.type,
content: this.content,
createdAt: this.createdAt,
imageUrl: this.imageUrl,
isPrivate: this.isPrivate,
privateLocked: this.privateLocked,
privateHint: this.privateHint,
audioUrl: this.audioUrl,
image: this.image,
lockDetail: this.lockDetail,
sessionId: this.sessionId,
};
}
@@ -81,12 +82,12 @@ export class LocalMessage {
return LocalMessage.from({
id: row.id,
role: row.role,
type: row.type,
content: row.content,
createdAt: row.createdAt,
imageUrl: row.imageUrl ?? null,
isPrivate: row.isPrivate ?? null,
privateLocked: row.privateLocked ?? null,
privateHint: row.privateHint ?? null,
audioUrl: row.audioUrl ?? null,
image: row.image,
lockDetail: row.lockDetail,
sessionId: row.sessionId,
});
}