import { z } from "zod"; const numberInput = z.union([z.string(), z.number()]); const optionalNumberInput = numberInput.optional(); const achievementTypeSchema = z.enum(["ordinary", "activity_limited"]); export const achievementFormSchema = z .object({ achievementType: achievementTypeSchema, description: z.string().trim().max(240, "描述不能超过 240 个字符").optional(), primaryBadgeResourceId: optionalNumberInput, title: z.string().trim().min(1, "请输入成就名称").max(64, "成就名称不能超过 64 个字符"), }) .superRefine((value, context) => { validateRequiredId(context, "primaryBadgeResourceId", value.primaryBadgeResourceId, "请选择徽章资源"); }); export type AchievementForm = z.infer; function validatePositiveInteger(context: z.RefinementCtx, path: string, value: unknown, message: string) { const numeric = Number(value); if (!Number.isInteger(numeric) || numeric <= 0) { context.addIssue({ code: "custom", message, path: path.split(".") }); } } function validateRequiredId(context: z.RefinementCtx, path: string, value: unknown, message: string) { const raw = String(value ?? "").trim(); if (!raw) { context.addIssue({ code: "custom", message, path: [path] }); return; } validatePositiveInteger(context, path, raw, message); }