From 76a1646cb7112e6e14111c56fba62f3a0fcb3c92 Mon Sep 17 00:00:00 2001 From: Caihaohan Date: Tue, 27 Jan 2026 19:30:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E8=AF=8D=E8=AF=8D=E4=BA=91=E7=B3=BB=E7=BB=9F=20Zod=20=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=20Schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/validations.ts | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/lib/validations.ts b/src/lib/validations.ts index 855786e..bdf4707 100644 --- a/src/lib/validations.ts +++ b/src/lib/validations.ts @@ -140,3 +140,75 @@ export type CreateDiscoveryTask = z.infer export type UpdateDiscoveryTask = z.infer export type GetDiscoveryTasksQuery = z.infer export type BatchResetTasks = z.infer + +// ================================ +// Keyword Cloud Schemas +// ================================ + +// 视觉配置 Schema +const VisualConfigSchema = z.object({ + color: z.enum(['primary', 'secondary', 'accent', 'gray']), + size: z.enum(['text-5xl', 'text-4xl', 'text-3xl', 'text-2xl', 'text-xl', 'text-lg', 'text-base']), + border: z.enum(['border-4', 'border-2']), + rotation: z.string().regex(/^-?rotate-\d+$/).nullable().optional(), +}) + +// 关键词输入 Schema +export const KeywordInputSchema = z.object({ + word: z.string().min(1).max(100), + trendScore: z.number().int().min(0).max(100), + description: z.string().min(10).max(500), + descriptionEn: z.string().max(500).optional(), + detailPoints: z.array(z.string().min(5).max(100)).min(1).max(5), + detailPointsEn: z.array(z.string().max(100)).max(5).optional(), + visualConfig: VisualConfigSchema, +}) + +// 批量写入关键词请求 Schema +export const BatchKeywordsRequestSchema = z.object({ + quarter: z.string().regex(/^\d{4}-Q[1-4]$/, "格式应为 YYYY-QN"), + keywords: z.array(KeywordInputSchema).min(1).max(50), +}) + +// 季度 Schema +export const QuarterSchema = z.object({ + quarter: z.string().regex(/^\d{4}-Q[1-4]$/), + title: z.string().min(1).max(200), + titleEn: z.string().max(200).optional(), + subtitle: z.string().max(500).optional(), + subtitleEn: z.string().max(500).optional(), + displayOrder: z.number().int().min(0).default(0), + isActive: z.boolean().default(true), +}) + +// 视觉规则 Schema +export const VisualStyleRuleSchema = z.object({ + name: z.string().min(1).max(100), + minScore: z.number().int().min(0).max(100), + maxScore: z.number().int().min(0).max(100), + color: z.enum(['primary', 'secondary', 'accent', 'gray']), + size: z.enum(['text-5xl', 'text-4xl', 'text-3xl', 'text-2xl', 'text-xl', 'text-lg', 'text-base']), + border: z.enum(['border-4', 'border-2']), + rotation: z.string().regex(/^-?rotate-\d+$/).nullable().optional(), + priority: z.number().int().min(0).default(0), + enabled: z.boolean().default(true), +}).refine(data => data.minScore < data.maxScore, { + message: "minScore 必须小于 maxScore", +}) + +// API 响应 Schema +export const KeywordCloudResponseSchema = z.object({ + success: z.boolean(), + data: z.any().optional(), + error: z.string().optional(), +}) + +// ================================ +// Types +// ================================ + +export type KeywordInput = z.infer +export type BatchKeywordsRequest = z.infer +export type Quarter = z.infer +export type VisualStyleRule = z.infer +export type KeywordCloudResponse = z.infer