优化小程序支付流程,新增订单插入逻辑,确保支付成功后更新订单状态并处理佣金分配。同时,重构阅读页面,增强权限管理和阅读追踪功能,提升用户体验。
This commit is contained in:
268
app/api/admin/distribution/overview/route.ts
Normal file
268
app/api/admin/distribution/overview/route.ts
Normal file
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* 管理端分销数据概览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 })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user