/** * 分销数据API - 使用 Prisma ORM * * 优势: * - ✅ 完全类型安全 * - ✅ 自动防SQL注入 * - ✅ 使用 Prisma 原生聚合查询 */ import { NextRequest, NextResponse } from 'next/server' import { prisma } from '@/lib/prisma' import { getPrismaConfig } from '@/lib/prisma-helpers' const DISTRIBUTOR_SHARE = 0.9 export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url) const userId = searchParams.get('userId') if (!userId) { return NextResponse.json({ success: false, error: '用户ID不能为空' }, { status: 400 }) } try { // 获取分销配置 let distributorShare = DISTRIBUTOR_SHARE let minWithdrawAmount = 10 try { const config = await getPrismaConfig('referral_config') if (config?.distributorShare) { distributorShare = config.distributorShare / 100 } if (config?.minWithdrawAmount) { minWithdrawAmount = Number(config.minWithdrawAmount) } } catch (e) { } // 1. 查询用户基本信息 const user = await prisma.users.findUnique({ where: { id: userId }, select: { id: true, nickname: true, referral_code: true, earnings: true, pending_earnings: true, withdrawn_earnings: true, referral_count: true } }) if (!user) { return NextResponse.json({ success: false, error: '用户不存在' }, { status: 404 }) } // 2. 使用 Prisma 聚合查询绑定统计 const [totalBindings, activeBindings, convertedBindings, expiredBindings] = await Promise.all([ prisma.referral_bindings.count({ where: { referrer_id: userId } }), prisma.referral_bindings.count({ where: { referrer_id: userId, status: 'active', expiry_date: { gt: new Date() } } }), prisma.referral_bindings.count({ where: { referrer_id: userId, status: 'active', purchase_count: { gt: 0 } } }), prisma.referral_bindings.count({ where: { referrer_id: userId, OR: [ { status: { in: ['expired', 'cancelled'] } }, { status: 'active', expiry_date: { lte: new Date() } } ] } }) ]) // 3. 付款统计(使用 Prisma 聚合) const paidOrders = await prisma.orders.aggregate({ where: { referrer_id: userId, status: 'paid' }, _count: { user_id: true }, _sum: { amount: true } }) const paidCount = await prisma.orders.findMany({ where: { referrer_id: userId, status: 'paid' }, distinct: ['user_id'], select: { user_id: true } }) const totalAmount = Number(paidOrders._sum.amount || 0) const uniquePaidCount = paidCount.length // 4. 访问统计 let totalVisits = totalBindings try { const visits = await prisma.referral_visits.groupBy({ by: ['visitor_id'], where: { referrer_id: userId } }) totalVisits = visits.length } catch (e) { console.log('[ReferralData] 访问统计表不存在') } // 5. 待审核 + 已成功提现金额(用提现表汇总,与 user.withdrawn_earnings 可能不一致时以表为准,避免可提现出现负数) const [pendingWithdraw, successWithdraw] = await Promise.all([ prisma.withdrawals.aggregate({ where: { user_id: userId, status: 'pending' }, _sum: { amount: true } }), prisma.withdrawals.aggregate({ where: { user_id: userId, status: 'success' }, _sum: { amount: true } }) ]) const pendingWithdrawAmount = Number(pendingWithdraw._sum.amount || 0) const withdrawnFromTable = Number(successWithdraw._sum.amount || 0) // 6. 获取活跃绑定用户列表 const activeBindingsList = await prisma.referral_bindings.findMany({ where: { referrer_id: userId, status: 'active', expiry_date: { gt: new Date() } }, take: 20, orderBy: { binding_date: 'desc' }, include: { users_referral_bindings_referee_idTousers: { select: { id: true, nickname: true, avatar: true, has_full_book: true } } } }) // 7. 获取已转化用户列表 const convertedBindingsList = await prisma.referral_bindings.findMany({ where: { referrer_id: userId, status: 'active', purchase_count: { gt: 0 } }, take: 20, orderBy: { last_purchase_date: 'desc' }, include: { users_referral_bindings_referee_idTousers: { select: { id: true, nickname: true, avatar: true } } } }) // 8. 获取已过期用户列表 const expiredBindingsList = await prisma.referral_bindings.findMany({ where: { referrer_id: userId, OR: [ { status: 'expired' }, { status: 'active', expiry_date: { lte: new Date() } } ] }, take: 20, orderBy: { expiry_date: 'desc' }, include: { users_referral_bindings_referee_idTousers: { select: { id: true, nickname: true, avatar: true } } } }) // 9. 获取收益明细 const earningsDetailsList = await prisma.orders.findMany({ where: { referrer_id: userId, status: 'paid' }, take: 20, orderBy: { pay_time: 'desc' }, include: { users: { select: { nickname: true, avatar: true } } } }) // 计算预估收益 const estimatedEarnings = totalAmount * distributorShare const totalCommission = totalAmount * distributorShare // 计算即将过期用户数(7天内) const now = new Date() const sevenDaysLater = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000) const expiringCount = activeBindingsList.filter(b => { const expiryDate = new Date(b.expiry_date) return expiryDate > now && expiryDate <= sevenDaysLater }).length return NextResponse.json({ success: true, data: { // 核心可见数据 bindingCount: activeBindings, visitCount: totalVisits, paidCount: uniquePaidCount, expiredCount: expiredBindings, // 收益数据 totalCommission: Math.round(totalCommission * 100) / 100, availableEarnings: Math.max(0, Math.round((totalCommission - withdrawnFromTable - pendingWithdrawAmount) * 100) / 100), pendingWithdrawAmount: Math.round(pendingWithdrawAmount * 100) / 100, withdrawnEarnings: withdrawnFromTable, earnings: Number(user.earnings) || 0, pendingEarnings: Number(user.pending_earnings) || 0, estimatedEarnings: Math.round(estimatedEarnings * 100) / 100, shareRate: Math.round(distributorShare * 100), minWithdrawAmount, // 推荐码 referralCode: user.referral_code, referralCount: user.referral_count || totalBindings, // 详细统计 stats: { totalBindings, activeBindings, convertedBindings, expiredBindings, expiringCount, totalPaymentAmount: totalAmount }, // 用户列表 activeUsers: activeBindingsList.map(b => { const daysRemaining = Math.max(0, Math.floor((new Date(b.expiry_date).getTime() - Date.now()) / (24 * 60 * 60 * 1000))) return { id: b.referee_id, nickname: b.users_referral_bindings_referee_idTousers.nickname || '用户' + b.referee_id.slice(-4), avatar: b.users_referral_bindings_referee_idTousers.avatar, daysRemaining, hasFullBook: b.users_referral_bindings_referee_idTousers.has_full_book, bindingDate: b.binding_date, status: 'active' } }), convertedUsers: convertedBindingsList.map(b => ({ id: b.referee_id, nickname: b.users_referral_bindings_referee_idTousers.nickname || '用户' + b.referee_id.slice(-4), avatar: b.users_referral_bindings_referee_idTousers.avatar, commission: Number(b.total_commission) || 0, orderAmount: Number(b.total_commission) / distributorShare || 0, purchaseCount: b.purchase_count || 0, conversionDate: b.last_purchase_date, status: 'converted' })), expiredUsers: expiredBindingsList.map(b => ({ id: b.referee_id, nickname: b.users_referral_bindings_referee_idTousers.nickname || '用户' + b.referee_id.slice(-4), avatar: b.users_referral_bindings_referee_idTousers.avatar, bindingDate: b.binding_date, expiryDate: b.expiry_date, status: 'expired' })), // 收益明细 earningsDetails: earningsDetailsList.map(e => ({ id: e.id, orderSn: e.order_sn, amount: Number(e.amount), commission: Number(e.amount) * distributorShare, productType: e.product_type, productId: e.product_id, description: e.description, buyerNickname: e.users.nickname || '用户' + e.id.slice(-4), buyerAvatar: e.users.avatar, payTime: e.pay_time })) } }) } catch (error) { console.error('[ReferralData] 错误:', error) return NextResponse.json({ success: false, error: '获取分销数据失败: ' + (error as Error).message }, { status: 500 }) } }