feat: 支持评分字段的导入
This commit is contained in:
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user