75e685d418
Reorganize the data layer by separating DTOs (Data Transfer Objects) from Zod validation schemas into distinct directory structures. Previously, all model types were imported from a single `@/data/models` barrel file, mixing request/response classes with validation schemas. Changes: - Update API files (auth, chat, metrics, user) to import DTOs from specific paths under `@/data/dto/*` instead of the models barrel - Move user schema to `@/data/schemas/user/user` for type-only imports - Create dedicated Zod schema files under `@/data/schemas/*` for auth and chat domain models (e.g., AppleLoginRequestSchema, SendMessageRequestSchema, SyncMessageSchema, SttDataSchema) - Improve discoverability and tree-shaking by co-locating schemas with their respective domain areas This is a non-functional refactor that lays the groundwork for clearer separation between transport-layer types and runtime validation.
99 lines
2.3 KiB
TypeScript
99 lines
2.3 KiB
TypeScript
/**
|
|
* 游客每日聊天配额数据 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);
|
|
}
|
|
}
|