"use client" import { useState, useEffect } from "react" import { Users, TrendingUp, Clock, Wallet, Search, RefreshCw, CheckCircle, XCircle, Zap, Calendar, DollarSign, Link2, Eye } from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" // 类型定义 interface DistributionOverview { todayClicks: number todayBindings: number todayConversions: number todayEarnings: number monthClicks: number monthBindings: number monthConversions: number monthEarnings: number totalClicks: number totalBindings: number totalConversions: number totalEarnings: number expiringBindings: number pendingWithdrawals: number pendingWithdrawAmount: number conversionRate: string totalDistributors: number activeDistributors: number } interface Binding { id: string referrer_id: string referrer_name?: string referrer_code: string referee_id: string referee_phone?: string referee_nickname?: string bound_at: string expires_at: string status: 'active' | 'converted' | 'expired' | 'cancelled' days_remaining?: number commission?: number order_amount?: number source?: string } interface Withdrawal { id: string user_id: string user_name?: string amount: number method: 'wechat' | 'alipay' account: string name: string status: 'pending' | 'completed' | 'rejected' created_at: string completed_at?: string } interface User { id: string nickname: string phone: string referral_code: string has_full_book: boolean earnings: number pending_earnings: number withdrawn_earnings: number referral_count: number created_at: string } // 订单类型(用于交易中心的订单管理标签) interface Order { id: string userId: string userNickname?: string userPhone?: string type: 'section' | 'fullbook' | 'match' sectionId?: string sectionTitle?: string amount: number status: 'pending' | 'completed' | 'failed' paymentMethod?: string referrerEarnings?: number createdAt: string } export default function DistributionAdminPage() { // 标签页:数据概览、订单管理、绑定管理、提现审核 const [activeTab, setActiveTab] = useState<'overview' | 'orders' | 'bindings' | 'withdrawals'>('overview') const [orders, setOrders] = useState([]) const [overview, setOverview] = useState(null) const [bindings, setBindings] = useState([]) const [withdrawals, setWithdrawals] = useState([]) const [users, setUsers] = useState([]) const [loading, setLoading] = useState(true) const [searchTerm, setSearchTerm] = useState('') const [statusFilter, setStatusFilter] = useState('all') useEffect(() => { loadData() }, [activeTab]) const loadData = async () => { setLoading(true) try { // 加载用户数据 const usersRes = await fetch('/api/db/users') const usersData = await usersRes.json() const usersArr = usersData.users || [] setUsers(usersArr) // 加载订单数据 const ordersRes = await fetch('/api/orders') const ordersData = await ordersRes.json() if (ordersData.success && ordersData.orders) { // 补充用户信息 const enrichedOrders = ordersData.orders.map((order: Order) => { const user = usersArr.find((u: User) => u.id === order.userId) return { ...order, userNickname: user?.nickname || '未知用户', userPhone: user?.phone || '-' } }) setOrders(enrichedOrders) } // 加载绑定数据 const bindingsRes = await fetch('/api/db/distribution') const bindingsData = await bindingsRes.json() setBindings(bindingsData.bindings || []) // 加载提现数据 const withdrawalsRes = await fetch('/api/db/withdrawals') const withdrawalsData = await withdrawalsRes.json() setWithdrawals(withdrawalsData.withdrawals || []) // 加载购买记录 const purchasesRes = await fetch('/api/db/purchases') const purchasesData = await purchasesRes.json() const purchases = purchasesData.purchases || [] // 计算概览数据 const today = new Date().toISOString().split('T')[0] const monthStart = new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString() const todayBindings = (bindingsData.bindings || []).filter((b: Binding) => b.bound_at?.startsWith(today) ).length const monthBindings = (bindingsData.bindings || []).filter((b: Binding) => b.bound_at >= monthStart ).length const todayConversions = (bindingsData.bindings || []).filter((b: Binding) => b.status === 'converted' && b.bound_at?.startsWith(today) ).length const monthConversions = (bindingsData.bindings || []).filter((b: Binding) => b.status === 'converted' && b.bound_at >= monthStart ).length const totalConversions = (bindingsData.bindings || []).filter((b: Binding) => b.status === 'converted' ).length // 计算佣金 const totalEarnings = usersArr.reduce((sum: number, u: User) => sum + (u.earnings || 0), 0) const pendingWithdrawAmount = (withdrawalsData.withdrawals || []) .filter((w: Withdrawal) => w.status === 'pending') .reduce((sum: number, w: Withdrawal) => sum + w.amount, 0) // 即将过期绑定(7天内) const sevenDaysLater = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString() const expiringBindings = (bindingsData.bindings || []).filter((b: Binding) => b.status === 'active' && b.expires_at <= sevenDaysLater && b.expires_at > new Date().toISOString() ).length setOverview({ todayClicks: Math.floor(Math.random() * 100) + 50, // 暂用模拟数据 todayBindings, todayConversions, todayEarnings: purchases.filter((p: any) => p.created_at?.startsWith(today)) .reduce((sum: number, p: any) => sum + (p.referrer_earnings || 0), 0), monthClicks: Math.floor(Math.random() * 1000) + 500, monthBindings, monthConversions, monthEarnings: purchases.filter((p: any) => p.created_at >= monthStart) .reduce((sum: number, p: any) => sum + (p.referrer_earnings || 0), 0), totalClicks: Math.floor(Math.random() * 5000) + 2000, totalBindings: (bindingsData.bindings || []).length, totalConversions, totalEarnings, expiringBindings, pendingWithdrawals: (withdrawalsData.withdrawals || []).filter((w: Withdrawal) => w.status === 'pending').length, pendingWithdrawAmount, conversionRate: ((bindingsData.bindings || []).length > 0 ? (totalConversions / (bindingsData.bindings || []).length * 100).toFixed(2) : '0'), totalDistributors: usersArr.filter((u: User) => u.referral_code).length, activeDistributors: usersArr.filter((u: User) => (u.earnings || 0) > 0).length, }) } catch (error) { console.error('Load distribution data error:', error) // 如果加载失败,设置空数据 setOverview({ todayClicks: 0, todayBindings: 0, todayConversions: 0, todayEarnings: 0, monthClicks: 0, monthBindings: 0, monthConversions: 0, monthEarnings: 0, totalClicks: 0, totalBindings: 0, totalConversions: 0, totalEarnings: 0, expiringBindings: 0, pendingWithdrawals: 0, pendingWithdrawAmount: 0, conversionRate: '0', totalDistributors: 0, activeDistributors: 0, }) } finally { setLoading(false) } } // 处理提现审核 const handleApproveWithdrawal = async (id: string) => { if (!confirm('确认审核通过并打款?')) return try { await fetch('/api/db/withdrawals', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id, status: 'completed' }) }) loadData() } catch (error) { console.error('Approve withdrawal error:', error) alert('操作失败') } } const handleRejectWithdrawal = async (id: string) => { const reason = prompt('请输入拒绝原因:') if (!reason) return try { await fetch('/api/db/withdrawals', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id, status: 'rejected' }) }) loadData() } catch (error) { console.error('Reject withdrawal error:', error) alert('操作失败') } } // 获取状态徽章 const getStatusBadge = (status: string) => { const styles: Record = { active: 'bg-green-500/20 text-green-400', converted: 'bg-blue-500/20 text-blue-400', expired: 'bg-gray-500/20 text-gray-400', cancelled: 'bg-red-500/20 text-red-400', pending: 'bg-orange-500/20 text-orange-400', completed: 'bg-green-500/20 text-green-400', rejected: 'bg-red-500/20 text-red-400', } const labels: Record = { active: '有效', converted: '已转化', expired: '已过期', cancelled: '已取消', pending: '待审核', completed: '已完成', rejected: '已拒绝', } return ( {labels[status] || status} ) } // 过滤数据 const filteredBindings = bindings.filter(b => { if (statusFilter !== 'all' && b.status !== statusFilter) return false if (searchTerm) { const term = searchTerm.toLowerCase() return ( b.referee_nickname?.toLowerCase().includes(term) || b.referee_phone?.includes(term) || b.referrer_name?.toLowerCase().includes(term) || b.referrer_code?.toLowerCase().includes(term) ) } return true }) const filteredWithdrawals = withdrawals.filter(w => { if (statusFilter !== 'all' && w.status !== statusFilter) return false if (searchTerm) { const term = searchTerm.toLowerCase() return ( w.user_name?.toLowerCase().includes(term) || w.account?.toLowerCase().includes(term) ) } return true }) return (
{/* 页面标题 */}

交易中心

统一管理:订单、分销绑定、提现审核

{/* Tab切换 - 交易中心:合并分销+订单+提现 */}
{[ { key: 'overview', label: '数据概览', icon: TrendingUp }, { key: 'orders', label: '订单管理', icon: DollarSign }, { key: 'bindings', label: '绑定管理', icon: Link2 }, { key: 'withdrawals', label: '提现审核', icon: Wallet }, ].map(tab => ( ))}
{loading ? (
加载中...
) : ( <> {/* 数据概览 */} {activeTab === 'overview' && overview && (
{/* 今日数据 */}

今日点击

{overview.todayClicks}

今日绑定

{overview.todayBindings}

今日转化

{overview.todayConversions}

今日佣金

¥{overview.todayEarnings.toFixed(2)}

{/* 重要提醒 */}

即将过期绑定

{overview.expiringBindings} 个

7天内到期,需关注转化

待审核提现

{overview.pendingWithdrawals} 笔

共 ¥{overview.pendingWithdrawAmount.toFixed(2)}

{/* 本月/累计统计 */}
本月统计

点击量

{overview.monthClicks}

绑定数

{overview.monthBindings}

转化数

{overview.monthConversions}

佣金

¥{overview.monthEarnings.toFixed(2)}

累计统计

总点击

{overview.totalClicks.toLocaleString()}

总绑定

{overview.totalBindings.toLocaleString()}

总转化

{overview.totalConversions}

总佣金

¥{overview.totalEarnings.toFixed(2)}

点击转化率 {overview.conversionRate}%
{/* 推广统计 */} 推广统计

{overview.totalDistributors}

推广用户数

{overview.activeDistributors}

有收益用户

90%

佣金比例

30天

绑定有效期

)} {/* 订单管理 - 新增标签页 */} {activeTab === 'orders' && (
setSearchTerm(e.target.value)} placeholder="搜索订单号、用户名、手机号..." className="pl-10 bg-[#0f2137] border-gray-700 text-white" />
{orders.length === 0 ? (
暂无订单数据
) : (
{orders .filter(order => { if (statusFilter !== 'all' && order.status !== statusFilter) return false if (searchTerm) { const term = searchTerm.toLowerCase() return ( order.id?.toLowerCase().includes(term) || order.userNickname?.toLowerCase().includes(term) || order.userPhone?.includes(term) || order.sectionTitle?.toLowerCase().includes(term) ) } return true }) .map(order => ( ))}
订单号 用户 商品 金额 支付方式 状态 分销佣金 下单时间
{order.id?.slice(0, 12)}...

{order.userNickname}

{order.userPhone}

{order.type === 'fullbook' ? '整本购买' : order.type === 'match' ? '匹配次数' : order.sectionTitle || `章节${order.sectionId}`}

{order.type === 'fullbook' ? '全书' : order.type === 'match' ? '功能' : '单章'}

¥{(order.amount || 0).toFixed(2)} {order.paymentMethod === 'wechat' ? '微信支付' : order.paymentMethod === 'alipay' ? '支付宝' : order.paymentMethod || '微信支付'} {order.status === 'completed' ? ( 已完成 ) : order.status === 'pending' ? ( 待支付 ) : ( 已失败 )} {order.referrerEarnings ? `¥${order.referrerEarnings.toFixed(2)}` : '-'} {order.createdAt ? new Date(order.createdAt).toLocaleString('zh-CN') : '-'}
)}
)} {/* 绑定管理 */} {activeTab === 'bindings' && (
setSearchTerm(e.target.value)} placeholder="搜索用户昵称、手机号、推广码..." className="pl-10 bg-[#0f2137] border-gray-700 text-white" />
{filteredBindings.length === 0 ? (
暂无绑定数据
) : (
{filteredBindings.map(binding => ( ))}
访客 分销商 绑定时间 到期时间 状态 佣金

{binding.referee_nickname || '匿名用户'}

{binding.referee_phone}

{binding.referrer_name || '-'}

{binding.referrer_code}

{binding.bound_at ? new Date(binding.bound_at).toLocaleDateString('zh-CN') : '-'} {binding.expires_at ? new Date(binding.expires_at).toLocaleDateString('zh-CN') : '-'} {getStatusBadge(binding.status)} {binding.commission ? ( ¥{binding.commission.toFixed(2)} ) : ( - )}
)}
)} {/* 提现审核 */} {activeTab === 'withdrawals' && (
setSearchTerm(e.target.value)} placeholder="搜索用户名称、账号..." className="pl-10 bg-[#0f2137] border-gray-700 text-white" />
{filteredWithdrawals.length === 0 ? (
暂无提现记录
) : (
{filteredWithdrawals.map(withdrawal => ( ))}
申请人 金额 收款方式 收款账号 申请时间 状态 操作

{withdrawal.user_name || withdrawal.name}

¥{withdrawal.amount.toFixed(2)} {withdrawal.method === 'wechat' ? '微信' : '支付宝'}

{withdrawal.account}

{withdrawal.name}

{withdrawal.created_at ? new Date(withdrawal.created_at).toLocaleString('zh-CN') : '-'} {getStatusBadge(withdrawal.status)} {withdrawal.status === 'pending' && (
)}
)}
)} )}
) }