2026-06-26 16:10:59 +08:00

35 lines
1.4 KiB
TypeScript

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<typeof achievementFormSchema>;
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);
}