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' // GET /api/wx-users/[id] - Get a wx user and all levels with completion state export async function GET( request: NextRequest, { params }: { params: Promise<{ id: string }> } ) { try { const session = await auth.api.getSession({ headers: request.headers, }) if (!session) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const { id } = await params // levelProgress 这里不按 sortKey 排——MySQL collation 不可靠。 // 下面用 progress 的 Map 按需组合,最终顺序由 levels 的 JS 排序决定。 const user = await prisma.wxUser.findUnique({ where: { id }, select: { id: true, openid: true, sessionKey: true, nickname: true, avatarUrl: true, stamina: true, staminaUpdatedAt: true, createdAt: true, updatedAt: true, levelProgress: { select: { id: true, userId: true, levelId: true, completedAt: true, timeSpent: true, }, }, }, }) if (!user) { return NextResponse.json({ error: 'User not found' }, { status: 404 }) } // sortKey 排序必须在 JS 侧做,避免大小写不敏感 collation 带来的顺序错乱 const levels = await prisma.level.findMany({ 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]) ) return NextResponse.json({ id: user.id, openid: user.openid, sessionKey: user.sessionKey, nickname: user.nickname, avatarUrl: user.avatarUrl, stamina: user.stamina, staminaUpdatedAt: user.staminaUpdatedAt, createdAt: user.createdAt, updatedAt: user.updatedAt, completedLevelCount: user.levelProgress.length, // 按 sortKey 排序后,数组下标即连续的 sortOrder,小程序端契约不变 assignedLevels: levels.map((level, index) => { const progress = progressByLevelId.get(level.id) return { id: level.id, answer: level.answer, sortOrder: index, completed: Boolean(progress), progressId: progress?.id || null, completedAt: progress?.completedAt || null, } }), }) } catch (error) { console.error('Error fetching wx user:', error) return NextResponse.json( { error: 'Failed to fetch wx user' }, { status: 500 } ) } }