/** * 分销服务 * 核心功能:绑定追踪、过期检测、佣金计算、自动提现 */ import type { DistributionBinding, Distributor, WithdrawRecord, ClickRecord, DistributionConfig, ExpireReminder, DistributionOverview, } from './types'; // 默认分销配置 export const DEFAULT_DISTRIBUTION_CONFIG: DistributionConfig = { bindingDays: 30, // 30天绑定期 bindingPriority: 'first', // 首次绑定优先 defaultCommissionRate: 90, // 默认90%佣金 levelRates: { normal: 90, silver: 92, gold: 95, diamond: 98, }, minWithdrawAmount: 10, // 最低10元提现 withdrawFeeRate: 0, // 0手续费 autoWithdrawEnabled: true, // 允许自动提现 autoWithdrawTime: '10:00', // 每天10点自动提现 expireRemindDays: 3, // 过期前3天提醒 enabled: true, }; // 存储键名 const STORAGE_KEYS = { BINDINGS: 'distribution_bindings', DISTRIBUTORS: 'distribution_distributors', WITHDRAWALS: 'distribution_withdrawals', CLICKS: 'distribution_clicks', CONFIG: 'distribution_config', REMINDERS: 'distribution_reminders', }; /** * 生成唯一ID */ function generateId(prefix: string = ''): string { return `${prefix}${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } /** * 获取配置 */ export function getDistributionConfig(): DistributionConfig { if (typeof window === 'undefined') return DEFAULT_DISTRIBUTION_CONFIG; const stored = localStorage.getItem(STORAGE_KEYS.CONFIG); return stored ? { ...DEFAULT_DISTRIBUTION_CONFIG, ...JSON.parse(stored) } : DEFAULT_DISTRIBUTION_CONFIG; } /** * 更新配置 */ export function updateDistributionConfig(config: Partial): DistributionConfig { if (typeof window === 'undefined') return DEFAULT_DISTRIBUTION_CONFIG; const current = getDistributionConfig(); const updated = { ...current, ...config }; localStorage.setItem(STORAGE_KEYS.CONFIG, JSON.stringify(updated)); return updated; } // ============== 绑定管理 ============== /** * 获取所有绑定 */ export function getAllBindings(): DistributionBinding[] { if (typeof window === 'undefined') return []; return JSON.parse(localStorage.getItem(STORAGE_KEYS.BINDINGS) || '[]'); } /** * 记录链接点击并创建绑定 */ export function recordClickAndBinding(params: { referralCode: string; referrerId: string; visitorId: string; visitorPhone?: string; visitorNickname?: string; source: 'link' | 'miniprogram' | 'poster' | 'qrcode'; sourceDetail?: string; deviceInfo?: DistributionBinding['deviceInfo']; }): { click: ClickRecord; binding: DistributionBinding | null } { if (typeof window === 'undefined') { return { click: {} as ClickRecord, binding: null }; } const config = getDistributionConfig(); const now = new Date(); // 1. 记录点击 const click: ClickRecord = { id: generateId('click_'), referralCode: params.referralCode, referrerId: params.referrerId, visitorId: params.visitorId, isNewVisitor: !hasExistingBinding(params.visitorId), source: params.source, deviceInfo: params.deviceInfo, registered: false, purchased: false, clickTime: now.toISOString(), createdAt: now.toISOString(), }; const clicks = JSON.parse(localStorage.getItem(STORAGE_KEYS.CLICKS) || '[]'); clicks.push(click); localStorage.setItem(STORAGE_KEYS.CLICKS, JSON.stringify(clicks)); // 2. 检查是否需要创建绑定 let binding: DistributionBinding | null = null; // 检查现有绑定 const existingBinding = getActiveBindingForVisitor(params.visitorId); if (!existingBinding || config.bindingPriority === 'last') { // 创建新绑定(如果没有现有绑定,或策略是"最后绑定") const expireDate = new Date(now); expireDate.setDate(expireDate.getDate() + config.bindingDays); binding = { id: generateId('bind_'), referrerId: params.referrerId, referrerCode: params.referralCode, visitorId: params.visitorId, visitorPhone: params.visitorPhone, visitorNickname: params.visitorNickname, bindingTime: now.toISOString(), expireTime: expireDate.toISOString(), status: 'active', source: params.source, sourceDetail: params.sourceDetail, deviceInfo: params.deviceInfo, createdAt: now.toISOString(), updatedAt: now.toISOString(), }; // 如果是"最后绑定"策略,先作废之前的绑定 if (existingBinding && config.bindingPriority === 'last') { cancelBinding(existingBinding.id, '新绑定覆盖'); } const bindings = getAllBindings(); bindings.push(binding); localStorage.setItem(STORAGE_KEYS.BINDINGS, JSON.stringify(bindings)); // 更新分销商统计 updateDistributorStats(params.referrerId); } return { click, binding }; } /** * 检查是否有现有绑定 */ function hasExistingBinding(visitorId: string): boolean { const bindings = getAllBindings(); return bindings.some(b => b.visitorId === visitorId); } /** * 获取访客的有效绑定 */ export function getActiveBindingForVisitor(visitorId: string): DistributionBinding | null { const bindings = getAllBindings(); const now = new Date(); return bindings.find(b => b.visitorId === visitorId && b.status === 'active' && new Date(b.expireTime) > now ) || null; } /** * 获取分销商的所有绑定 */ export function getBindingsForDistributor(referrerId: string): DistributionBinding[] { const bindings = getAllBindings(); return bindings.filter(b => b.referrerId === referrerId); } /** * 取消绑定 */ export function cancelBinding(bindingId: string, reason?: string): boolean { const bindings = getAllBindings(); const index = bindings.findIndex(b => b.id === bindingId); if (index === -1) return false; bindings[index] = { ...bindings[index], status: 'cancelled', updatedAt: new Date().toISOString(), }; localStorage.setItem(STORAGE_KEYS.BINDINGS, JSON.stringify(bindings)); return true; } /** * 将绑定标记为已转化(用户付款后调用) */ export function convertBinding(params: { visitorId: string; orderId: string; orderAmount: number; }): { binding: DistributionBinding | null; commission: number } { const binding = getActiveBindingForVisitor(params.visitorId); if (!binding) { return { binding: null, commission: 0 }; } const config = getDistributionConfig(); const distributor = getDistributor(binding.referrerId); const commissionRate = distributor?.commissionRate || config.defaultCommissionRate; const commission = params.orderAmount * (commissionRate / 100); // 更新绑定状态 const bindings = getAllBindings(); const index = bindings.findIndex(b => b.id === binding.id); if (index !== -1) { bindings[index] = { ...bindings[index], status: 'converted', convertedAt: new Date().toISOString(), orderId: params.orderId, orderAmount: params.orderAmount, commission, updatedAt: new Date().toISOString(), }; localStorage.setItem(STORAGE_KEYS.BINDINGS, JSON.stringify(bindings)); // 更新分销商收益 addDistributorEarnings(binding.referrerId, commission); // 更新点击记录 updateClickPurchaseStatus(binding.referrerId, params.visitorId); } return { binding: bindings[index], commission }; } /** * 检查并处理过期绑定 */ export function processExpiredBindings(): { expired: DistributionBinding[]; expiringSoon: DistributionBinding[]; } { const bindings = getAllBindings(); const config = getDistributionConfig(); const now = new Date(); const remindThreshold = new Date(); remindThreshold.setDate(remindThreshold.getDate() + config.expireRemindDays); const expired: DistributionBinding[] = []; const expiringSoon: DistributionBinding[] = []; const updatedBindings = bindings.map(binding => { if (binding.status !== 'active') return binding; const expireTime = new Date(binding.expireTime); if (expireTime <= now) { // 已过期 expired.push(binding); createExpireReminder(binding, 'expired'); return { ...binding, status: 'expired' as const, updatedAt: now.toISOString(), }; } else if (expireTime <= remindThreshold) { // 即将过期 const daysRemaining = Math.ceil((expireTime.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)); expiringSoon.push(binding); createExpireReminder(binding, 'expiring_soon', daysRemaining); } return binding; }); localStorage.setItem(STORAGE_KEYS.BINDINGS, JSON.stringify(updatedBindings)); // 更新相关分销商统计 const affectedDistributors = new Set([ ...expired.map(b => b.referrerId), ...expiringSoon.map(b => b.referrerId), ]); affectedDistributors.forEach(distributorId => { updateDistributorStats(distributorId); }); return { expired, expiringSoon }; } // ============== 提醒管理 ============== /** * 创建过期提醒 */ function createExpireReminder( binding: DistributionBinding, type: 'expiring_soon' | 'expired', daysRemaining?: number ): void { const reminders = JSON.parse(localStorage.getItem(STORAGE_KEYS.REMINDERS) || '[]') as ExpireReminder[]; // 检查是否已存在相同提醒 const exists = reminders.some(r => r.bindingId === binding.id && r.reminderType === type ); if (exists) return; const reminder: ExpireReminder = { id: generateId('remind_'), bindingId: binding.id, distributorId: binding.referrerId, bindingInfo: { visitorNickname: binding.visitorNickname, visitorPhone: binding.visitorPhone, bindingTime: binding.bindingTime, expireTime: binding.expireTime, }, reminderType: type, daysRemaining, isRead: false, createdAt: new Date().toISOString(), }; reminders.push(reminder); localStorage.setItem(STORAGE_KEYS.REMINDERS, JSON.stringify(reminders)); } /** * 获取分销商的提醒 */ export function getRemindersForDistributor(distributorId: string): ExpireReminder[] { const reminders = JSON.parse(localStorage.getItem(STORAGE_KEYS.REMINDERS) || '[]') as ExpireReminder[]; return reminders.filter(r => r.distributorId === distributorId); } /** * 获取未读提醒数量 */ export function getUnreadReminderCount(distributorId: string): number { const reminders = getRemindersForDistributor(distributorId); return reminders.filter(r => !r.isRead).length; } /** * 标记提醒已读 */ export function markReminderRead(reminderId: string): void { const reminders = JSON.parse(localStorage.getItem(STORAGE_KEYS.REMINDERS) || '[]') as ExpireReminder[]; const index = reminders.findIndex(r => r.id === reminderId); if (index !== -1) { reminders[index].isRead = true; reminders[index].readAt = new Date().toISOString(); localStorage.setItem(STORAGE_KEYS.REMINDERS, JSON.stringify(reminders)); } } // ============== 分销商管理 ============== /** * 获取分销商信息 */ export function getDistributor(userId: string): Distributor | null { const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; return distributors.find(d => d.userId === userId) || null; } /** * 获取或创建分销商 */ export function getOrCreateDistributor(params: { userId: string; nickname: string; phone: string; referralCode: string; }): Distributor { let distributor = getDistributor(params.userId); if (!distributor) { const config = getDistributionConfig(); distributor = { id: generateId('dist_'), userId: params.userId, nickname: params.nickname, phone: params.phone, referralCode: params.referralCode, totalClicks: 0, totalBindings: 0, activeBindings: 0, convertedBindings: 0, expiredBindings: 0, totalEarnings: 0, pendingEarnings: 0, withdrawnEarnings: 0, autoWithdraw: false, autoWithdrawThreshold: config.minWithdrawAmount, level: 'normal', commissionRate: config.defaultCommissionRate, status: 'active', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; distributors.push(distributor); localStorage.setItem(STORAGE_KEYS.DISTRIBUTORS, JSON.stringify(distributors)); } return distributor; } /** * 更新分销商统计 */ function updateDistributorStats(userId: string): void { const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; const index = distributors.findIndex(d => d.userId === userId); if (index === -1) return; const bindings = getBindingsForDistributor(userId); const clicks = JSON.parse(localStorage.getItem(STORAGE_KEYS.CLICKS) || '[]') as ClickRecord[]; const userClicks = clicks.filter(c => c.referrerId === userId); distributors[index] = { ...distributors[index], totalClicks: userClicks.length, totalBindings: bindings.length, activeBindings: bindings.filter(b => b.status === 'active').length, convertedBindings: bindings.filter(b => b.status === 'converted').length, expiredBindings: bindings.filter(b => b.status === 'expired').length, updatedAt: new Date().toISOString(), }; localStorage.setItem(STORAGE_KEYS.DISTRIBUTORS, JSON.stringify(distributors)); } /** * 增加分销商收益 */ function addDistributorEarnings(userId: string, amount: number): void { const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; const index = distributors.findIndex(d => d.userId === userId); if (index === -1) return; distributors[index] = { ...distributors[index], totalEarnings: distributors[index].totalEarnings + amount, pendingEarnings: distributors[index].pendingEarnings + amount, updatedAt: new Date().toISOString(), }; localStorage.setItem(STORAGE_KEYS.DISTRIBUTORS, JSON.stringify(distributors)); // 检查是否需要自动提现 checkAutoWithdraw(distributors[index]); } /** * 更新点击记录的购买状态 */ function updateClickPurchaseStatus(referrerId: string, visitorId: string): void { const clicks = JSON.parse(localStorage.getItem(STORAGE_KEYS.CLICKS) || '[]') as ClickRecord[]; const index = clicks.findIndex(c => c.referrerId === referrerId && c.visitorId === visitorId); if (index !== -1) { clicks[index].purchased = true; clicks[index].purchasedAt = new Date().toISOString(); localStorage.setItem(STORAGE_KEYS.CLICKS, JSON.stringify(clicks)); } } /** * 设置自动提现 */ export function setAutoWithdraw(params: { userId: string; enabled: boolean; threshold?: number; account?: Distributor['autoWithdrawAccount']; }): boolean { const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; const index = distributors.findIndex(d => d.userId === params.userId); if (index === -1) return false; distributors[index] = { ...distributors[index], autoWithdraw: params.enabled, autoWithdrawThreshold: params.threshold || distributors[index].autoWithdrawThreshold, autoWithdrawAccount: params.account || distributors[index].autoWithdrawAccount, updatedAt: new Date().toISOString(), }; localStorage.setItem(STORAGE_KEYS.DISTRIBUTORS, JSON.stringify(distributors)); return true; } // ============== 提现管理 ============== /** * 获取所有提现记录 */ export function getAllWithdrawals(): WithdrawRecord[] { if (typeof window === 'undefined') return []; return JSON.parse(localStorage.getItem(STORAGE_KEYS.WITHDRAWALS) || '[]'); } /** * 获取分销商的提现记录 */ export function getWithdrawalsForDistributor(distributorId: string): WithdrawRecord[] { const withdrawals = getAllWithdrawals(); return withdrawals.filter(w => w.distributorId === distributorId); } /** * 申请提现 */ export function requestWithdraw(params: { userId: string; amount: number; method: 'wechat' | 'alipay'; account: string; accountName: string; }): { success: boolean; withdrawal?: WithdrawRecord; error?: string } { const config = getDistributionConfig(); const distributor = getDistributor(params.userId); if (!distributor) { return { success: false, error: '分销商不存在' }; } if (params.amount < config.minWithdrawAmount) { return { success: false, error: `最低提现金额为 ${config.minWithdrawAmount} 元` }; } if (params.amount > distributor.pendingEarnings) { return { success: false, error: '提现金额超过可提现余额' }; } const fee = params.amount * config.withdrawFeeRate; const actualAmount = params.amount - fee; const withdrawal: WithdrawRecord = { id: generateId('withdraw_'), distributorId: distributor.id, userId: params.userId, userName: distributor.nickname, amount: params.amount, fee, actualAmount, method: params.method, account: params.account, accountName: params.accountName, status: 'pending', isAuto: false, createdAt: new Date().toISOString(), }; // 保存提现记录 const withdrawals = getAllWithdrawals(); withdrawals.push(withdrawal); localStorage.setItem(STORAGE_KEYS.WITHDRAWALS, JSON.stringify(withdrawals)); // 扣除待提现金额 deductDistributorPendingEarnings(params.userId, params.amount); return { success: true, withdrawal }; } /** * 扣除分销商待提现金额 */ function deductDistributorPendingEarnings(userId: string, amount: number): void { const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; const index = distributors.findIndex(d => d.userId === userId); if (index !== -1) { distributors[index].pendingEarnings -= amount; localStorage.setItem(STORAGE_KEYS.DISTRIBUTORS, JSON.stringify(distributors)); } } /** * 检查并执行自动提现 */ function checkAutoWithdraw(distributor: Distributor): void { if (!distributor.autoWithdraw || !distributor.autoWithdrawAccount) { return; } if (distributor.pendingEarnings >= distributor.autoWithdrawThreshold) { // 执行自动提现 const result = executeAutoWithdraw(distributor); if (result.success) { console.log(`自动提现成功: ${distributor.nickname}, 金额: ${distributor.pendingEarnings}`); } } } /** * 执行自动提现 */ export function executeAutoWithdraw(distributor: Distributor): { success: boolean; withdrawal?: WithdrawRecord; error?: string } { if (!distributor.autoWithdrawAccount) { return { success: false, error: '未配置自动提现账户' }; } const config = getDistributionConfig(); const amount = distributor.pendingEarnings; const fee = amount * config.withdrawFeeRate; const actualAmount = amount - fee; const withdrawal: WithdrawRecord = { id: generateId('withdraw_'), distributorId: distributor.id, userId: distributor.userId, userName: distributor.nickname, amount, fee, actualAmount, method: distributor.autoWithdrawAccount.type, account: distributor.autoWithdrawAccount.account, accountName: distributor.autoWithdrawAccount.name, status: 'processing', // 自动提现直接进入处理状态 isAuto: true, createdAt: new Date().toISOString(), }; // 保存提现记录 const withdrawals = getAllWithdrawals(); withdrawals.push(withdrawal); localStorage.setItem(STORAGE_KEYS.WITHDRAWALS, JSON.stringify(withdrawals)); // 扣除待提现金额 deductDistributorPendingEarnings(distributor.userId, amount); // 这里应该调用实际的支付接口进行打款 // 实际项目中需要对接微信/支付宝的企业付款接口 processWithdrawalPayment(withdrawal.id); return { success: true, withdrawal }; } /** * 处理提现打款(模拟) * 实际项目中需要对接支付接口 */ export async function processWithdrawalPayment(withdrawalId: string): Promise<{ success: boolean; error?: string }> { const withdrawals = getAllWithdrawals(); const index = withdrawals.findIndex(w => w.id === withdrawalId); if (index === -1) { return { success: false, error: '提现记录不存在' }; } const withdrawal = withdrawals[index]; // 模拟支付接口调用 // 实际项目中应该调用: // - 微信:企业付款到零钱 API // - 支付宝:单笔转账到支付宝账户 API try { // 模拟网络延迟 await new Promise(resolve => setTimeout(resolve, 1000)); // 更新提现状态为成功 withdrawals[index] = { ...withdrawal, status: 'completed', paymentNo: `PAY${Date.now()}`, paymentTime: new Date().toISOString(), completedAt: new Date().toISOString(), }; localStorage.setItem(STORAGE_KEYS.WITHDRAWALS, JSON.stringify(withdrawals)); // 更新分销商已提现金额 const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; const distIndex = distributors.findIndex(d => d.userId === withdrawal.userId); if (distIndex !== -1) { distributors[distIndex].withdrawnEarnings += withdrawal.amount; localStorage.setItem(STORAGE_KEYS.DISTRIBUTORS, JSON.stringify(distributors)); } return { success: true }; } catch (error) { // 打款失败 withdrawals[index] = { ...withdrawal, status: 'failed', paymentError: error instanceof Error ? error.message : '打款失败', }; localStorage.setItem(STORAGE_KEYS.WITHDRAWALS, JSON.stringify(withdrawals)); // 退还金额到待提现余额 const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; const distIndex = distributors.findIndex(d => d.userId === withdrawal.userId); if (distIndex !== -1) { distributors[distIndex].pendingEarnings += withdrawal.amount; localStorage.setItem(STORAGE_KEYS.DISTRIBUTORS, JSON.stringify(distributors)); } return { success: false, error: '打款失败' }; } } /** * 审核通过并打款 */ export async function approveWithdrawal(withdrawalId: string, reviewedBy?: string): Promise<{ success: boolean; error?: string }> { const withdrawals = getAllWithdrawals(); const index = withdrawals.findIndex(w => w.id === withdrawalId); if (index === -1) { return { success: false, error: '提现记录不存在' }; } if (withdrawals[index].status !== 'pending') { return { success: false, error: '该提现申请已处理' }; } withdrawals[index] = { ...withdrawals[index], status: 'processing', reviewedBy, reviewedAt: new Date().toISOString(), }; localStorage.setItem(STORAGE_KEYS.WITHDRAWALS, JSON.stringify(withdrawals)); // 执行打款 return processWithdrawalPayment(withdrawalId); } /** * 拒绝提现 */ export function rejectWithdrawal(withdrawalId: string, reason: string, reviewedBy?: string): { success: boolean; error?: string } { const withdrawals = getAllWithdrawals(); const index = withdrawals.findIndex(w => w.id === withdrawalId); if (index === -1) { return { success: false, error: '提现记录不存在' }; } const withdrawal = withdrawals[index]; if (withdrawal.status !== 'pending') { return { success: false, error: '该提现申请已处理' }; } withdrawals[index] = { ...withdrawal, status: 'rejected', reviewNote: reason, reviewedBy, reviewedAt: new Date().toISOString(), }; localStorage.setItem(STORAGE_KEYS.WITHDRAWALS, JSON.stringify(withdrawals)); // 退还金额到待提现余额 const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; const distIndex = distributors.findIndex(d => d.userId === withdrawal.userId); if (distIndex !== -1) { distributors[distIndex].pendingEarnings += withdrawal.amount; localStorage.setItem(STORAGE_KEYS.DISTRIBUTORS, JSON.stringify(distributors)); } return { success: true }; } // ============== 统计概览 ============== /** * 获取分销统计概览 */ export function getDistributionOverview(): DistributionOverview { const bindings = getAllBindings(); const clicks = JSON.parse(localStorage.getItem(STORAGE_KEYS.CLICKS) || '[]') as ClickRecord[]; const withdrawals = getAllWithdrawals(); const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const monthStart = new Date(now.getFullYear(), now.getMonth(), 1); const weekFromNow = new Date(); weekFromNow.setDate(weekFromNow.getDate() + 7); // 今日数据 const todayClicks = clicks.filter(c => new Date(c.clickTime) >= today).length; const todayBindings = bindings.filter(b => new Date(b.createdAt) >= today).length; const todayConversions = bindings.filter(b => b.status === 'converted' && b.convertedAt && new Date(b.convertedAt) >= today ).length; const todayEarnings = bindings .filter(b => b.status === 'converted' && b.convertedAt && new Date(b.convertedAt) >= today) .reduce((sum, b) => sum + (b.commission || 0), 0); // 本月数据 const monthClicks = clicks.filter(c => new Date(c.clickTime) >= monthStart).length; const monthBindings = bindings.filter(b => new Date(b.createdAt) >= monthStart).length; const monthConversions = bindings.filter(b => b.status === 'converted' && b.convertedAt && new Date(b.convertedAt) >= monthStart ).length; const monthEarnings = bindings .filter(b => b.status === 'converted' && b.convertedAt && new Date(b.convertedAt) >= monthStart) .reduce((sum, b) => sum + (b.commission || 0), 0); // 总计数据 const totalConversions = bindings.filter(b => b.status === 'converted').length; const totalEarnings = bindings .filter(b => b.status === 'converted') .reduce((sum, b) => sum + (b.commission || 0), 0); // 即将过期数据 const expiringBindings = bindings.filter(b => b.status === 'active' && new Date(b.expireTime) <= weekFromNow && new Date(b.expireTime) > now ).length; const expiredToday = bindings.filter(b => b.status === 'expired' && b.updatedAt && new Date(b.updatedAt) >= today ).length; // 提现数据 const pendingWithdrawals = withdrawals.filter(w => w.status === 'pending').length; const pendingWithdrawAmount = withdrawals .filter(w => w.status === 'pending') .reduce((sum, w) => sum + w.amount, 0); // 转化率 const conversionRate = clicks.length > 0 ? (totalConversions / clicks.length) * 100 : 0; return { todayClicks, todayBindings, todayConversions, todayEarnings, monthClicks, monthBindings, monthConversions, monthEarnings, totalClicks: clicks.length, totalBindings: bindings.length, totalConversions, totalEarnings, expiringBindings, expiredToday, pendingWithdrawals, pendingWithdrawAmount, conversionRate, lastUpdated: now.toISOString(), }; } /** * 获取分销排行榜 */ export function getDistributionRanking(limit: number = 10): Distributor[] { const distributors = JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]') as Distributor[]; return distributors .filter(d => d.status === 'active') .sort((a, b) => b.totalEarnings - a.totalEarnings) .slice(0, limit); } /** * 获取所有分销商 */ export function getAllDistributors(): Distributor[] { if (typeof window === 'undefined') return []; return JSON.parse(localStorage.getItem(STORAGE_KEYS.DISTRIBUTORS) || '[]'); }