Files
soul-yongping/app/api/admin/distribution/overview/route.ts

269 lines
9.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.

/**
* 管理端分销数据概览API - 从真实数据库查询
*/
import { NextRequest, NextResponse } from 'next/server'
import { query } from '@/lib/db'
import { requireAdminResponse } from '@/lib/admin-auth'
export async function GET(req: NextRequest) {
// 验证管理员权限
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const now = new Date()
const today = now.toISOString().split('T')[0]
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1).toISOString()
const sevenDaysLater = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString()
// === 1. 订单数据统计 ===
let orderStats = {
todayOrders: 0,
todayAmount: 0,
monthOrders: 0,
monthAmount: 0,
totalOrders: 0,
totalAmount: 0
}
try {
const orderResults = await query(`
SELECT
COUNT(*) as total_count,
COALESCE(SUM(amount), 0) as total_amount,
COALESCE(SUM(CASE WHEN DATE(created_at) = ? THEN 1 ELSE 0 END), 0) as today_count,
COALESCE(SUM(CASE WHEN DATE(created_at) = ? THEN amount ELSE 0 END), 0) as today_amount,
COALESCE(SUM(CASE WHEN created_at >= ? THEN 1 ELSE 0 END), 0) as month_count,
COALESCE(SUM(CASE WHEN created_at >= ? THEN amount ELSE 0 END), 0) as month_amount
FROM orders
WHERE status = 'paid'
`, [today, today, monthStart, monthStart]) as any[]
if (orderResults.length > 0) {
const r = orderResults[0]
orderStats = {
todayOrders: parseInt(r.today_count) || 0,
todayAmount: parseFloat(r.today_amount) || 0,
monthOrders: parseInt(r.month_count) || 0,
monthAmount: parseFloat(r.month_amount) || 0,
totalOrders: parseInt(r.total_count) || 0,
totalAmount: parseFloat(r.total_amount) || 0
}
}
} catch (e) {
console.error('[Admin Overview] 订单统计失败:', e)
}
// === 2. 绑定数据统计 ===
let bindingStats = {
todayBindings: 0,
todayConversions: 0,
monthBindings: 0,
monthConversions: 0,
totalBindings: 0,
totalConversions: 0,
activeBindings: 0,
expiredBindings: 0,
expiringBindings: 0
}
try {
const bindingResults = await query(`
SELECT
COUNT(*) as total_count,
SUM(CASE WHEN status = 'active' AND expiry_date > NOW() THEN 1 ELSE 0 END) as active_count,
SUM(CASE WHEN status = 'converted' THEN 1 ELSE 0 END) as converted_count,
SUM(CASE WHEN status = 'expired' OR (status = 'active' AND expiry_date <= NOW()) THEN 1 ELSE 0 END) as expired_count,
SUM(CASE WHEN DATE(binding_date) = ? THEN 1 ELSE 0 END) as today_count,
SUM(CASE WHEN DATE(binding_date) = ? AND status = 'converted' THEN 1 ELSE 0 END) as today_converted,
SUM(CASE WHEN binding_date >= ? THEN 1 ELSE 0 END) as month_count,
SUM(CASE WHEN binding_date >= ? AND status = 'converted' THEN 1 ELSE 0 END) as month_converted,
SUM(CASE WHEN status = 'active' AND expiry_date <= ? AND expiry_date > NOW() THEN 1 ELSE 0 END) as expiring_count
FROM referral_bindings
`, [today, today, monthStart, monthStart, sevenDaysLater]) as any[]
if (bindingResults.length > 0) {
const r = bindingResults[0]
bindingStats = {
todayBindings: parseInt(r.today_count) || 0,
todayConversions: parseInt(r.today_converted) || 0,
monthBindings: parseInt(r.month_count) || 0,
monthConversions: parseInt(r.month_converted) || 0,
totalBindings: parseInt(r.total_count) || 0,
totalConversions: parseInt(r.converted_count) || 0,
activeBindings: parseInt(r.active_count) || 0,
expiredBindings: parseInt(r.expired_count) || 0,
expiringBindings: parseInt(r.expiring_count) || 0
}
}
} catch (e) {
console.error('[Admin Overview] 绑定统计失败:', e)
}
// === 3. 收益数据统计 ===
let earningsStats = {
totalEarnings: 0,
todayEarnings: 0,
monthEarnings: 0,
pendingEarnings: 0
}
try {
// 从 users 表累加所有用户的收益
const earningsResults = await query(`
SELECT
COALESCE(SUM(earnings), 0) as total_earnings,
COALESCE(SUM(pending_earnings), 0) as pending_earnings
FROM users
`) as any[]
if (earningsResults.length > 0) {
earningsStats.totalEarnings = parseFloat(earningsResults[0].total_earnings) || 0
earningsStats.pendingEarnings = parseFloat(earningsResults[0].pending_earnings) || 0
}
// 今日和本月收益:从 orders 表计算status='paid' 的订单)
const periodEarningsResults = await query(`
SELECT
COALESCE(SUM(CASE WHEN DATE(pay_time) = ? THEN amount * 0.9 ELSE 0 END), 0) as today_earnings,
COALESCE(SUM(CASE WHEN pay_time >= ? THEN amount * 0.9 ELSE 0 END), 0) as month_earnings
FROM orders
WHERE status = 'paid'
`, [today, monthStart]) as any[]
if (periodEarningsResults.length > 0) {
earningsStats.todayEarnings = parseFloat(periodEarningsResults[0].today_earnings) || 0
earningsStats.monthEarnings = parseFloat(periodEarningsResults[0].month_earnings) || 0
}
} catch (e) {
console.error('[Admin Overview] 收益统计失败:', e)
}
// === 4. 提现数据统计 ===
let withdrawalStats = {
pendingCount: 0,
pendingAmount: 0
}
try {
const withdrawalResults = await query(`
SELECT
COUNT(*) as pending_count,
COALESCE(SUM(amount), 0) as pending_amount
FROM withdrawals
WHERE status = 'pending'
`) as any[]
if (withdrawalResults.length > 0) {
withdrawalStats.pendingCount = parseInt(withdrawalResults[0].pending_count) || 0
withdrawalStats.pendingAmount = parseFloat(withdrawalResults[0].pending_amount) || 0
}
} catch (e) {
console.error('[Admin Overview] 提现统计失败:', e)
}
// === 5. 访问数据统计 ===
let visitStats = {
todayVisits: 0,
monthVisits: 0,
totalVisits: 0
}
try {
const visitResults = await query(`
SELECT
COUNT(*) as total_count,
COUNT(DISTINCT CASE WHEN DATE(created_at) = ? THEN id END) as today_count,
COUNT(DISTINCT CASE WHEN created_at >= ? THEN id END) as month_count
FROM referral_visits
`, [today, monthStart]) as any[]
if (visitResults.length > 0) {
visitStats.totalVisits = parseInt(visitResults[0].total_count) || 0
visitStats.todayVisits = parseInt(visitResults[0].today_count) || 0
visitStats.monthVisits = parseInt(visitResults[0].month_count) || 0
}
} catch (e) {
console.error('[Admin Overview] 访问统计失败:', e)
// 访问表可能不存在,使用绑定数作为替代
visitStats = {
todayVisits: bindingStats.todayBindings,
monthVisits: bindingStats.monthBindings,
totalVisits: bindingStats.totalBindings
}
}
// === 6. 分销商数据统计 ===
let distributorStats = {
totalDistributors: 0,
activeDistributors: 0
}
try {
const distributorResults = await query(`
SELECT
COUNT(*) as total_count,
SUM(CASE WHEN earnings > 0 THEN 1 ELSE 0 END) as active_count
FROM users
WHERE referral_code IS NOT NULL AND referral_code != ''
`) as any[]
if (distributorResults.length > 0) {
distributorStats.totalDistributors = parseInt(distributorResults[0].total_count) || 0
distributorStats.activeDistributors = parseInt(distributorResults[0].active_count) || 0
}
} catch (e) {
console.error('[Admin Overview] 分销商统计失败:', e)
}
// === 7. 计算转化率 ===
const conversionRate = visitStats.totalVisits > 0
? ((bindingStats.totalConversions / visitStats.totalVisits) * 100).toFixed(2)
: '0.00'
// 返回完整概览数据
const overview = {
// 今日数据
todayClicks: visitStats.todayVisits,
todayBindings: bindingStats.todayBindings,
todayConversions: bindingStats.todayConversions,
todayEarnings: earningsStats.todayEarnings,
// 本月数据
monthClicks: visitStats.monthVisits,
monthBindings: bindingStats.monthBindings,
monthConversions: bindingStats.monthConversions,
monthEarnings: earningsStats.monthEarnings,
// 总计数据
totalClicks: visitStats.totalVisits,
totalBindings: bindingStats.totalBindings,
totalConversions: bindingStats.totalConversions,
totalEarnings: earningsStats.totalEarnings,
// 其他统计
expiringBindings: bindingStats.expiringBindings,
pendingWithdrawals: withdrawalStats.pendingCount,
pendingWithdrawAmount: withdrawalStats.pendingAmount,
conversionRate,
totalDistributors: distributorStats.totalDistributors,
activeDistributors: distributorStats.activeDistributors,
}
console.log('[Admin Overview] 数据统计完成:', overview)
return NextResponse.json({
success: true,
overview
})
} catch (error) {
console.error('[Admin Overview] 统计失败:', error)
return NextResponse.json({
success: false,
error: '获取分销概览失败: ' + (error as Error).message
}, { status: 500 })
}
}