269 lines
9.4 KiB
TypeScript
269 lines
9.4 KiB
TypeScript
/**
|
||
* 管理端分销数据概览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 })
|
||
}
|
||
}
|