You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
1.8 KiB
74 lines
1.8 KiB
import type { ZodIssue } from "zod"
|
|
|
|
const FIELD_LABELS: Record<string, string> = {
|
|
type: "类型",
|
|
title: "标题",
|
|
description: "描述",
|
|
aspectRatio: "宽高比",
|
|
categoryId: "分类",
|
|
images: "图片",
|
|
tagIds: "标签",
|
|
url: "图片地址",
|
|
sortOrder: "排序",
|
|
name: "名称",
|
|
slug: "标识",
|
|
image: "封面图片",
|
|
parentId: "上级分类",
|
|
icon: "图标",
|
|
content: "内容",
|
|
summary: "摘要",
|
|
cover: "封面图",
|
|
status: "状态",
|
|
cardIds: "关联卡片",
|
|
cardId: "卡片 ID",
|
|
articleIds: "关联文章",
|
|
}
|
|
|
|
function fieldLabel(path: readonly (string | number)[]): string {
|
|
const key = path.join(".")
|
|
return FIELD_LABELS[key] || key || "字段"
|
|
}
|
|
|
|
export function formatZodErrors(issues: ZodIssue[]): string {
|
|
if (issues.length === 0) return "请求数据有误"
|
|
|
|
const first = issues[0]!
|
|
const label = fieldLabel(first.path as (string | number)[])
|
|
|
|
// Use the built-in message if available and specific enough
|
|
if (first.message && first.message !== "Required") {
|
|
return first.message
|
|
}
|
|
|
|
switch (first.code) {
|
|
case "too_small":
|
|
return `${label}不能为空`
|
|
case "too_big":
|
|
return `${label}太长`
|
|
case "invalid_type":
|
|
return `${label}格式不正确`
|
|
default:
|
|
return `${label}: ${first.message}`
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wraps a Zod schema parse and throws a 422 with Chinese message on failure
|
|
*/
|
|
export function validate<T>(
|
|
schema: {
|
|
safeParse: (data: unknown) =>
|
|
| { success: true; data: T }
|
|
| { success: false; error: { issues: ZodIssue[] } }
|
|
},
|
|
data: unknown,
|
|
): T {
|
|
const result = schema.safeParse(data)
|
|
if (!result.success) {
|
|
throw createError({
|
|
statusCode: 422,
|
|
statusMessage: formatZodErrors(result.error.issues),
|
|
})
|
|
}
|
|
return result.data
|
|
}
|
|
|