WuYongJie f646b71813
Some checks failed
CI Check / check (push) Has been cancelled
chore: 初始化本地仓库并同步最近改动
2025-11-18 17:50:16 +08:00

123 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { randomBytes } from 'crypto'
import { resolveBaseUrl } from '@/lib/config'
// GET - 获取邀请链接列表(仅管理员)
export async function GET(req: NextRequest) {
try {
const session = await getServerSession(authOptions)
const isSuperAdmin = (session?.user as any)?.isSuperAdmin
if (!session || ((session.user as any)?.role !== 'ADMIN' && !isSuperAdmin)) {
return NextResponse.json(
{ error: '无权限' },
{ status: 403 }
)
}
// 支持分页
const { searchParams } = new URL(req.url)
const page = parseInt(searchParams.get('page') || '1', 10)
const pageSize = Math.min(parseInt(searchParams.get('pageSize') || '20', 10), 100) // 最大100条
const skip = (page - 1) * pageSize
// 并行查询总数和数据
const [total, invitations] = await Promise.all([
prisma.invitation.count(),
prisma.invitation.findMany({
orderBy: { createdAt: 'desc' },
skip,
take: pageSize,
select: {
id: true,
code: true,
createdBy: true,
maxUses: true,
currentUses: true,
expiresAt: true,
isActive: true,
createdAt: true,
// 不返回敏感信息
}
})
])
// 生成完整邀请链接(统一使用集中配置策略)
const baseUrl = resolveBaseUrl(req)
const invitationsWithUrl = invitations.map(invitation => ({
...invitation,
inviteUrl: `${baseUrl}/register?invite=${invitation.code}`,
}))
return NextResponse.json({
invitations: invitationsWithUrl,
pagination: {
page,
pageSize,
total,
totalPages: Math.ceil(total / pageSize)
}
})
} catch (error) {
console.error('[Invitations] GET error:', error)
return NextResponse.json(
{ error: '获取邀请链接失败' },
{ status: 500 }
)
}
}
// POST - 创建邀请链接(仅管理员)
export async function POST(req: NextRequest) {
try {
const session = await getServerSession(authOptions)
const isSuperAdmin = (session?.user as any)?.isSuperAdmin
if (!session || ((session.user as any)?.role !== 'ADMIN' && !isSuperAdmin)) {
return NextResponse.json(
{ error: '无权限' },
{ status: 403 }
)
}
const { maxUses, expiresInDays } = await req.json()
const userId = (session.user as any).id
// 生成唯一邀请码(8位随机字符串)
const code = randomBytes(4).toString('hex').toUpperCase()
// 计算过期时间
const expiresAt = expiresInDays
? new Date(Date.now() + expiresInDays * 24 * 60 * 60 * 1000)
: null
const invitation = await prisma.invitation.create({
data: {
code,
createdBy: userId,
maxUses: maxUses || 1,
expiresAt,
},
})
// 生成完整邀请链接(统一使用集中配置策略)
const baseUrl = resolveBaseUrl(req)
const inviteUrl = `${baseUrl}/register?invite=${code}`
return NextResponse.json({
...invitation,
inviteUrl,
})
} catch (error) {
console.error('[Invitations] POST error:', error)
return NextResponse.json(
{ error: '创建邀请链接失败' },
{ status: 500 }
)
}
}