import { serverRequest } from "./serverConnection"; export interface BetaApplicationInput { name: string; phone: string; wechat: string; industry: string; company: string; city: string; aiTools: string; aiDuration: string; aiTrack: string; aiDirection: string[]; weeklyUsage: string; feedbackWilling: string; wantFeature: string[]; selfStatement: string; signature: string; agreeRules: boolean; } export type BetaApplicationStatus = "pending" | "approved" | "rejected"; export interface BetaApplicationItem extends BetaApplicationInput { id: number; userId: number | null; username: string | null; status: BetaApplicationStatus; inviteCode: string | null; reviewNote: string | null; reviewedBy: number | null; reviewerUsername: string | null; reviewedAt: string | null; ipAddress: string | null; userAgent: string | null; createdAt: string; updatedAt: string; } export interface BetaApplicationSubmitResult { id: number; status: BetaApplicationStatus; createdAt: string; } function readString(value: unknown): string { return typeof value === "string" ? value : ""; } function readNullableString(value: unknown): string | null { return typeof value === "string" && value ? value : null; } function readNumberOrNull(value: unknown): number | null { if (value === null || value === undefined || value === "") return null; const next = Number(value); return Number.isFinite(next) ? next : null; } function readStringArray(value: unknown): string[] { return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : []; } function normalizeStatus(value: unknown): BetaApplicationStatus { return value === "approved" || value === "rejected" ? value : "pending"; } function normalizeApplication(raw: unknown): BetaApplicationItem { const item = raw && typeof raw === "object" && !Array.isArray(raw) ? (raw as Record) : {}; return { id: Number(item.id) || 0, userId: readNumberOrNull(item.userId), username: readNullableString(item.username), name: readString(item.name), phone: readString(item.phone), wechat: readString(item.wechat), industry: readString(item.industry), company: readString(item.company), city: readString(item.city), aiTools: readString(item.aiTools), aiDuration: readString(item.aiDuration), aiTrack: readString(item.aiTrack), aiDirection: readStringArray(item.aiDirection), weeklyUsage: readString(item.weeklyUsage), feedbackWilling: readString(item.feedbackWilling), wantFeature: readStringArray(item.wantFeature), selfStatement: readString(item.selfStatement), signature: readString(item.signature), agreeRules: item.agreeRules === true, status: normalizeStatus(item.status), inviteCode: readNullableString(item.inviteCode), reviewNote: readNullableString(item.reviewNote), reviewedBy: readNumberOrNull(item.reviewedBy), reviewerUsername: readNullableString(item.reviewerUsername), reviewedAt: readNullableString(item.reviewedAt), ipAddress: readNullableString(item.ipAddress), userAgent: readNullableString(item.userAgent), createdAt: readString(item.createdAt), updatedAt: readString(item.updatedAt), }; } export const betaApplicationClient = { async submit(input: BetaApplicationInput): Promise { const payload = await serverRequest<{ application: BetaApplicationSubmitResult }>("beta-applications", { method: "POST", body: input, maxRetries: 0, fallbackMessage: "提交内测申请失败", }); return payload.application; }, async listAdminApplications(status?: BetaApplicationStatus | ""): Promise { const query = status ? `?status=${encodeURIComponent(status)}` : ""; const payload = await serverRequest<{ applications?: unknown[] }>(`admin/beta-applications${query}`, { fallbackMessage: "读取内测申请失败", }); return Array.isArray(payload.applications) ? payload.applications.map(normalizeApplication) : []; }, async reviewApplication( id: number, action: "approve" | "reject", reviewNote?: string, ): Promise { const payload = await serverRequest<{ application: unknown }>(`admin/beta-applications/${id}`, { method: "PATCH", body: { action, reviewNote }, maxRetries: 0, fallbackMessage: "审核内测申请失败", }); return normalizeApplication(payload.application); }, };