From b25822aa618a189da7703c007f0567bf51ed9d33 Mon Sep 17 00:00:00 2001 From: 18631081161 <2088094923@qq.com> Date: Wed, 24 Dec 2025 14:15:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/views/users/index.vue | 20 ++++-- backend/src/services/adminUserService.js | 27 ++++++-- backend/src/services/invitationService.js | 67 ++++++++++++++----- backend/src/services/paymentOrderService.js | 6 +- .../src/pages/me/invite-reward-page.vue | 34 +++++++--- 5 files changed, 115 insertions(+), 39 deletions(-) diff --git a/admin/src/views/users/index.vue b/admin/src/views/users/index.vue index d898009..450b59a 100644 --- a/admin/src/views/users/index.vue +++ b/admin/src/views/users/index.vue @@ -202,9 +202,9 @@ 累计奖励(¥) ¥{{ parseFloat(userDetails.invitations.totalRewardsRmb || userDetails.invitations.totalRewards || 0).toFixed(2) }} -
+
累计奖励(₱) - ₱{{ parseFloat(userDetails.invitations.totalRewardsPeso || 0).toFixed(2) }} + ₱{{ parseFloat(userDetails.invitations.totalRewardsPeso || 0).toFixed(2) }}
@@ -225,8 +225,20 @@ {{ userDetails.withdrawals.total }}
- 提现金额 - ¥{{ parseFloat(userDetails.withdrawals.totalAmount || 0).toFixed(2) }} + 已提现(¥) + ¥{{ userDetails.withdrawals.totalAmountRmb || '0.00' }} +
+
+ 已提现(₱) + ₱{{ userDetails.withdrawals.totalAmountPeso || '0.00' }} +
+
+ 待提现(¥) + ¥{{ userDetails.withdrawals.pendingBalanceRmb || '0.00' }} +
+
+ 待提现(₱) + ₱{{ userDetails.withdrawals.pendingBalancePeso || '0.00' }}
待审核 diff --git a/backend/src/services/adminUserService.js b/backend/src/services/adminUserService.js index 3a6a538..9db5736 100644 --- a/backend/src/services/adminUserService.js +++ b/backend/src/services/adminUserService.js @@ -271,16 +271,19 @@ const getUserDetails = async (userId) => { where: { userId }, attributes: [ 'status', + 'currency', [require('sequelize').fn('COUNT', require('sequelize').col('id')), 'count'], [require('sequelize').fn('SUM', require('sequelize').col('amount')), 'total'], ], - group: ['status'], + group: ['status', 'currency'], raw: true, }); const withdrawalCounts = { total: 0, totalAmount: 0, + totalAmountRmb: 0, + totalAmountPeso: 0, waiting: 0, processing: 0, completed: 0, @@ -288,11 +291,27 @@ const getUserDetails = async (userId) => { }; withdrawalStats.forEach((stat) => { - withdrawalCounts[stat.status] = parseInt(stat.count); - withdrawalCounts.total += parseInt(stat.count); - withdrawalCounts.totalAmount += parseFloat(stat.total || 0); + const count = parseInt(stat.count); + const amount = parseFloat(stat.total || 0); + + withdrawalCounts[stat.status] = (withdrawalCounts[stat.status] || 0) + count; + withdrawalCounts.total += count; + withdrawalCounts.totalAmount += amount; + + // 按货币类型统计提现金额 + if (stat.currency === 'PHP') { + withdrawalCounts.totalAmountPeso += amount; + } else { + withdrawalCounts.totalAmountRmb += amount; + } }); + // Add pending balance by currency from user model + withdrawalCounts.pendingBalanceRmb = parseFloat(user.balance || 0).toFixed(2); + withdrawalCounts.pendingBalancePeso = parseFloat(user.balancePeso || 0).toFixed(2); + withdrawalCounts.totalAmountRmb = withdrawalCounts.totalAmountRmb.toFixed(2); + withdrawalCounts.totalAmountPeso = withdrawalCounts.totalAmountPeso.toFixed(2); + // Get recent login history const loginHistory = await LoginHistory.findAll({ where: { userId, userType: 'user' }, diff --git a/backend/src/services/invitationService.js b/backend/src/services/invitationService.js index 52c68e0..b6ee8fd 100644 --- a/backend/src/services/invitationService.js +++ b/backend/src/services/invitationService.js @@ -104,24 +104,57 @@ const getInvitationRecords = async (userId, options = {}) => { offset: parseInt(offset), }); + // Get commission data for each invitee from Commission table + const Commission = require('../models/Commission'); + // Format records - filter out records where invitee was deleted - const records = rows - .filter(invitation => invitation.invitee != null) - .map(invitation => ({ - id: invitation.id, - invitee: { - id: invitation.invitee.id, - uid: invitation.invitee.uid, - nickname: invitation.invitee.nickname, - avatar: invitation.invitee.avatar, - registeredAt: invitation.registeredAt, - }, - firstPaymentAt: invitation.firstPaymentAt, - firstPaymentAmount: invitation.firstPaymentAmount ? parseFloat(invitation.firstPaymentAmount).toFixed(2) : null, - rewardAmount: invitation.rewardAmount ? parseFloat(invitation.rewardAmount).toFixed(2) : null, - rewardStatus: invitation.rewardStatus, - createdAt: invitation.createdAt, - })); + const records = await Promise.all( + rows + .filter(invitation => invitation.invitee != null) + .map(async (invitation) => { + // Get total commission for this invitee from Commission table + const commissions = await Commission.findAll({ + where: { + inviterId: userId, + inviteeId: invitation.invitee.id, + status: 'credited' + }, + attributes: ['commissionAmount', 'currency'], + }); + + let totalRewardRmb = 0; + let totalRewardPeso = 0; + let hasPaid = false; + + commissions.forEach(c => { + hasPaid = true; + const amount = parseFloat(c.commissionAmount || 0); + if (c.currency === 'PHP') { + totalRewardPeso += amount; + } else { + totalRewardRmb += amount; + } + }); + + return { + id: invitation.id, + invitee: { + id: invitation.invitee.id, + uid: invitation.invitee.uid, + nickname: invitation.invitee.nickname, + avatar: invitation.invitee.avatar, + registeredAt: invitation.registeredAt, + }, + firstPaymentAt: hasPaid ? (invitation.firstPaymentAt || new Date()) : null, + rewardAmountRmb: totalRewardRmb.toFixed(2), + rewardAmountPeso: totalRewardPeso.toFixed(2), + // Legacy field for backward compatibility + rewardAmount: (totalRewardRmb + totalRewardPeso).toFixed(2), + rewardStatus: hasPaid ? 'credited' : 'pending', + createdAt: invitation.createdAt, + }; + }) + ); return { records, diff --git a/backend/src/services/paymentOrderService.js b/backend/src/services/paymentOrderService.js index 2ff36c9..444257b 100644 --- a/backend/src/services/paymentOrderService.js +++ b/backend/src/services/paymentOrderService.js @@ -98,8 +98,8 @@ const createPaymentOrder = async (data, adminId) => { exists = !!existingOrder; } - // Calculate total amount for commission (use RMB if available) - const totalAmountForCommission = rmbAmount > 0 ? rmbAmount : legacyAmount; + // Calculate total amount for commission (check any currency) + const totalAmountForCommission = rmbAmount > 0 ? rmbAmount : (pesoAmount > 0 ? pesoAmount : legacyAmount); // Create payment order const paymentOrder = await PaymentOrder.create({ @@ -116,7 +116,7 @@ const createPaymentOrder = async (data, adminId) => { status: 'active', }); - // Calculate commission (if applicable, based on RMB amount) + // Calculate commission (if applicable, for any currency) let commission = null; if (totalAmountForCommission > 0) { try { diff --git a/miniprogram/src/pages/me/invite-reward-page.vue b/miniprogram/src/pages/me/invite-reward-page.vue index 4c287c5..e52cd07 100644 --- a/miniprogram/src/pages/me/invite-reward-page.vue +++ b/miniprogram/src/pages/me/invite-reward-page.vue @@ -124,8 +124,8 @@ {{ item.uid }} {{ item.time }} - - ¥0 + + @@ -468,13 +468,20 @@ console.log('GetInvitationRecords response:', res) // 后端返回格式: { code: 0, message: "", data: { records: [...] } } if (res && res.code === 0 && res.data && res.data.records) { - this.inviteRecords = res.data.records.map(item => ({ - username: item.invitee?.nickname || '-', - uid: item.invitee?.uid || '-', - time: this.formatDate(item.createdAt), - paid: item.firstPaymentAt != null, - amount: item.rewardAmount ? parseFloat(item.rewardAmount) : 0 - })) + this.inviteRecords = res.data.records.map(item => { + const rewardRmb = parseFloat(item.rewardAmountRmb || 0) + const rewardPeso = parseFloat(item.rewardAmountPeso || 0) + return { + username: item.invitee?.nickname || '-', + uid: item.invitee?.uid || '-', + time: this.formatDate(item.createdAt), + paid: item.firstPaymentAt != null, + rewardRmb: rewardRmb, + rewardPeso: rewardPeso, + // Legacy field + amount: item.rewardAmount ? parseFloat(item.rewardAmount) : 0 + } + }) } } catch (error) { console.error('获取邀请记录失败:', error) @@ -1305,13 +1312,18 @@ &.status-cell { display: flex; + flex-direction: column; align-items: center; justify-content: center; .paid-amount { - font-size: 28rpx; + font-size: 26rpx; font-weight: bold; - color: #333333; + color: #FF3B4E; + + &.peso { + color: #67c23a; + } } .unpaid-text {