|
1 | | -/** |
2 | | - * @description: 活动横幅所需要的类型 |
3 | | - * @param name 活动名称 |
4 | | - * @param discord discord活动链接 |
5 | | - * @param playback 回放链接 |
6 | | - * @param coverUrl 封面地址 |
7 | | - * @param deprecated 是否已经结束 |
8 | | - */ |
9 | | -export interface ActivityEvent { |
| 1 | +import { z } from "zod"; |
| 2 | +import eventsJson from "@/data/event.json"; |
| 3 | + |
| 4 | +export const ActivityEventSchema = z.object({ |
10 | 5 | /** 活动名称,用于轮播标题 */ |
11 | | - name: string; |
| 6 | + name: z.string().min(1, "name 不能为空"), |
12 | 7 | /** Discord 活动入口链接 */ |
13 | | - discord: string; |
| 8 | + discord: z.string().min(1, "discord 入口不能为空"), |
14 | 9 | /** 活动回放链接,deprecated 为 true 时展示 */ |
15 | | - playback?: string; |
| 10 | + playback: z.string().min(1, "playback 链接不能为空").optional(), |
16 | 11 | /** 活动封面,可以是静态资源相对路径或完整 URL */ |
17 | | - coverUrl: string; |
| 12 | + coverUrl: z.string().min(1, "coverUrl 不能为空"), |
18 | 13 | /** 是否为已结束活动,true 时展示 Playback 按钮 */ |
19 | | - deprecated: boolean; |
20 | | -} |
| 14 | + deprecated: z.boolean(), |
| 15 | +}); |
21 | 16 |
|
22 | | -/** 活动轮播可配置参数 */ |
23 | | -export interface ActivityTickerSettings { |
| 17 | +export const ActivityTickerSettingsSchema = z.object({ |
24 | 18 | /** 首屏最多展示的活动数量 */ |
25 | | - maxItems: number; |
| 19 | + maxItems: z.number().int().positive("maxItems 需要为正整数"), |
26 | 20 | /** 自动轮播的间隔时间(毫秒) */ |
27 | | - rotationIntervalMs: number; |
28 | | -} |
| 21 | + rotationIntervalMs: z |
| 22 | + .number() |
| 23 | + .int() |
| 24 | + .positive("rotationIntervalMs 需要为正整数"), |
| 25 | +}); |
| 26 | + |
| 27 | +export const ActivityEventsConfigSchema = z.object({ |
| 28 | + settings: ActivityTickerSettingsSchema, |
| 29 | + events: z.array(ActivityEventSchema), |
| 30 | +}); |
29 | 31 |
|
30 | | -/** event.json 的整体结构 */ |
31 | | -export interface ActivityEventsConfig { |
32 | | - settings: ActivityTickerSettings; |
33 | | - events: ActivityEvent[]; |
| 32 | +type ActivityEvent = z.infer<typeof ActivityEventSchema>; |
| 33 | +type ActivityTickerSettings = z.infer<typeof ActivityTickerSettingsSchema>; |
| 34 | +type ActivityEventsConfig = z.infer<typeof ActivityEventsConfigSchema>; |
| 35 | + |
| 36 | +const parsedEventsConfig = ActivityEventsConfigSchema.safeParse(eventsJson); |
| 37 | + |
| 38 | +if (!parsedEventsConfig.success) { |
| 39 | + const issueMessages = parsedEventsConfig.error.issues |
| 40 | + .map((issue) => `- ${issue.path.join(".") || "(root)"}: ${issue.message}`) |
| 41 | + .join("\n"); |
| 42 | + throw new Error(`event.json 配置不合法:\n${issueMessages}`); |
34 | 43 | } |
| 44 | + |
| 45 | +export const activityEventsConfig: ActivityEventsConfig = |
| 46 | + parsedEventsConfig.data; |
| 47 | + |
| 48 | +export type { ActivityEvent, ActivityEventsConfig, ActivityTickerSettings }; |
0 commit comments