feat: 支持批量上传关卡

This commit is contained in:
richarjiang
2026-05-01 08:44:56 +08:00
parent f3f27def2b
commit 66a9ee2950
27 changed files with 5262 additions and 515 deletions

View File

@@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
import { auth } from '@/lib/auth'
import { compareSortKey } from '@/lib/sort-key'
export const dynamic = 'force-dynamic'
@@ -20,6 +21,8 @@ export async function GET(
const { id } = await params
// levelProgress 这里不按 sortKey 排——MySQL collation 不可靠。
// 下面用 progress 的 Map 按需组合,最终顺序由 levels 的 JS 排序决定。
const user = await prisma.wxUser.findUnique({
where: { id },
select: {
@@ -33,23 +36,12 @@ export async function GET(
createdAt: true,
updatedAt: true,
levelProgress: {
orderBy: [
{ level: { sortOrder: 'asc' } },
{ completedAt: 'desc' },
],
select: {
id: true,
userId: true,
levelId: true,
completedAt: true,
timeSpent: true,
level: {
select: {
id: true,
answer: true,
sortOrder: true,
},
},
},
},
},
@@ -59,14 +51,22 @@ export async function GET(
return NextResponse.json({ error: 'User not found' }, { status: 404 })
}
// sortKey 排序必须在 JS 侧做,避免大小写不敏感 collation 带来的顺序错乱
const levels = await prisma.level.findMany({
orderBy: { sortOrder: 'asc' },
select: {
id: true,
answer: true,
sortKey: true,
sortOrder: true,
createdAt: true,
},
})
levels.sort((a, b) => {
const c = compareSortKey(a.sortKey, b.sortKey)
if (c !== 0) return c
if (a.sortOrder !== b.sortOrder) return a.sortOrder - b.sortOrder
return a.createdAt.getTime() - b.createdAt.getTime()
})
const progressByLevelId = new Map(
user.levelProgress.map((progress) => [progress.levelId, progress])
@@ -83,13 +83,14 @@ export async function GET(
createdAt: user.createdAt,
updatedAt: user.updatedAt,
completedLevelCount: user.levelProgress.length,
assignedLevels: levels.map((level) => {
// 按 sortKey 排序后,数组下标即连续的 sortOrder小程序端契约不变
assignedLevels: levels.map((level, index) => {
const progress = progressByLevelId.get(level.id)
return {
id: level.id,
answer: level.answer,
sortOrder: level.sortOrder,
sortOrder: index,
completed: Boolean(progress),
progressId: progress?.id || null,
completedAt: progress?.completedAt || null,