feat: 支持评分字段的导入

This commit is contained in:
richarjiang
2026-06-07 09:50:03 +08:00
parent e0b88e68e9
commit 588b6fbc77
8 changed files with 193 additions and 24 deletions

View File

@@ -70,6 +70,21 @@ function parseRiddleId(raw: unknown): string | null {
return riddleId
}
/**
* 解析评分:
* - undefined / null / '' → null视为未评分
* - 1-5 整数 → 原样返回
* - 其它 → 抛错
*/
function parseScore(raw: unknown): number | null {
if (raw === undefined || raw === null || raw === '') return null
const n = typeof raw === 'number' ? raw : Number(raw)
if (!Number.isInteger(n) || n < 1 || n > 5) {
throw new Error('评分必须是 1-5 之间的整数')
}
return n
}
function optionalString(raw: unknown): string | null {
return raw ? String(raw) : null
}
@@ -85,6 +100,8 @@ function buildLevelData(body: Record<string, unknown>) {
hint1: optionalString(body.hint1),
hint2: optionalString(body.hint2),
hint3: optionalString(body.hint3),
difficultyScore: parseScore(body.difficultyScore),
funScore: parseScore(body.funScore),
}
}
@@ -112,9 +129,11 @@ export async function POST(request: NextRequest) {
let position: number | undefined
let riddleId: string | null
let data: ReturnType<typeof buildLevelData>
try {
position = parsePosition(body.position)
riddleId = parseRiddleId(body.riddleId)
data = buildLevelData(body)
} catch (e) {
return NextResponse.json(
{ error: e instanceof Error ? e.message : 'invalid level payload' },
@@ -122,32 +141,18 @@ export async function POST(request: NextRequest) {
)
}
const data = buildLevelData(body)
if (riddleId) {
const existing = await prisma.level.findUnique({
where: { riddleId },
})
if (existing) {
let newSortKey: string | undefined
if (position !== undefined) {
const total = await prisma.level.count()
if (position > total) {
return NextResponse.json(
{ error: `position 超出范围,合法区间 [1, ${total}]` },
{ status: 400 }
)
}
newSortKey = await keyForPosition(position, existing.id)
}
// 命中存量关卡 → 只更新内容字段,绝不动 sortKey / sortOrder。
// 关卡顺序由用户在系统里手动维护,批量导入不能覆盖。
// 注意position 在此分支被显式忽略(即便客户端误传也不会被处理)。
const level = await prisma.level.update({
where: { id: existing.id },
data: {
...data,
...(newSortKey ? { sortKey: newSortKey } : {}),
},
data, // buildLevelData 不包含 sortKey
})
return NextResponse.json(level)
@@ -207,11 +212,13 @@ export async function PUT(request: NextRequest) {
}
let position: number | undefined
let data: ReturnType<typeof buildLevelData>
try {
position = parsePosition(body.position)
data = buildLevelData(body)
} catch (e) {
return NextResponse.json(
{ error: e instanceof Error ? e.message : 'invalid position' },
{ error: e instanceof Error ? e.message : 'invalid level payload' },
{ status: 400 }
)
}
@@ -229,8 +236,6 @@ export async function PUT(request: NextRequest) {
newSortKey = await keyForPosition(position, id)
}
const data = buildLevelData(body)
const level = await prisma.level.update({
where: { id },
data: {