This commit is contained in:
18631081161 2025-12-24 14:15:36 +08:00
parent 2e90b3e4b2
commit b25822aa61
5 changed files with 115 additions and 39 deletions

View File

@ -202,9 +202,9 @@
<span class="label">累计奖励(¥)</span> <span class="label">累计奖励(¥)</span>
<span class="value primary">¥{{ parseFloat(userDetails.invitations.totalRewardsRmb || userDetails.invitations.totalRewards || 0).toFixed(2) }}</span> <span class="value primary">¥{{ parseFloat(userDetails.invitations.totalRewardsRmb || userDetails.invitations.totalRewards || 0).toFixed(2) }}</span>
</div> </div>
<div class="stat-item" v-if="parseFloat(userDetails.invitations.totalRewardsPeso || 0) > 0"> <div class="stat-item">
<span class="label">累计奖励()</span> <span class="label">累计奖励()</span>
<span class="value primary">{{ parseFloat(userDetails.invitations.totalRewardsPeso || 0).toFixed(2) }}</span> <span class="value success">{{ parseFloat(userDetails.invitations.totalRewardsPeso || 0).toFixed(2) }}</span>
</div> </div>
</div> </div>
</el-card> </el-card>
@ -225,8 +225,20 @@
<span class="value">{{ userDetails.withdrawals.total }}</span> <span class="value">{{ userDetails.withdrawals.total }}</span>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<span class="label">提现金额</span> <span class="label">已提现(¥)</span>
<span class="value primary">¥{{ parseFloat(userDetails.withdrawals.totalAmount || 0).toFixed(2) }}</span> <span class="value primary">¥{{ userDetails.withdrawals.totalAmountRmb || '0.00' }}</span>
</div>
<div class="stat-item">
<span class="label">已提现()</span>
<span class="value success">{{ userDetails.withdrawals.totalAmountPeso || '0.00' }}</span>
</div>
<div class="stat-item">
<span class="label">待提现(¥)</span>
<span class="value primary">¥{{ userDetails.withdrawals.pendingBalanceRmb || '0.00' }}</span>
</div>
<div class="stat-item">
<span class="label">待提现()</span>
<span class="value success">{{ userDetails.withdrawals.pendingBalancePeso || '0.00' }}</span>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<span class="label">待审核</span> <span class="label">待审核</span>

View File

@ -271,16 +271,19 @@ const getUserDetails = async (userId) => {
where: { userId }, where: { userId },
attributes: [ attributes: [
'status', 'status',
'currency',
[require('sequelize').fn('COUNT', require('sequelize').col('id')), 'count'], [require('sequelize').fn('COUNT', require('sequelize').col('id')), 'count'],
[require('sequelize').fn('SUM', require('sequelize').col('amount')), 'total'], [require('sequelize').fn('SUM', require('sequelize').col('amount')), 'total'],
], ],
group: ['status'], group: ['status', 'currency'],
raw: true, raw: true,
}); });
const withdrawalCounts = { const withdrawalCounts = {
total: 0, total: 0,
totalAmount: 0, totalAmount: 0,
totalAmountRmb: 0,
totalAmountPeso: 0,
waiting: 0, waiting: 0,
processing: 0, processing: 0,
completed: 0, completed: 0,
@ -288,11 +291,27 @@ const getUserDetails = async (userId) => {
}; };
withdrawalStats.forEach((stat) => { withdrawalStats.forEach((stat) => {
withdrawalCounts[stat.status] = parseInt(stat.count); const count = parseInt(stat.count);
withdrawalCounts.total += parseInt(stat.count); const amount = parseFloat(stat.total || 0);
withdrawalCounts.totalAmount += 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 // Get recent login history
const loginHistory = await LoginHistory.findAll({ const loginHistory = await LoginHistory.findAll({
where: { userId, userType: 'user' }, where: { userId, userType: 'user' },

View File

@ -104,10 +104,39 @@ const getInvitationRecords = async (userId, options = {}) => {
offset: parseInt(offset), 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 // Format records - filter out records where invitee was deleted
const records = rows const records = await Promise.all(
rows
.filter(invitation => invitation.invitee != null) .filter(invitation => invitation.invitee != null)
.map(invitation => ({ .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, id: invitation.id,
invitee: { invitee: {
id: invitation.invitee.id, id: invitation.invitee.id,
@ -116,12 +145,16 @@ const getInvitationRecords = async (userId, options = {}) => {
avatar: invitation.invitee.avatar, avatar: invitation.invitee.avatar,
registeredAt: invitation.registeredAt, registeredAt: invitation.registeredAt,
}, },
firstPaymentAt: invitation.firstPaymentAt, firstPaymentAt: hasPaid ? (invitation.firstPaymentAt || new Date()) : null,
firstPaymentAmount: invitation.firstPaymentAmount ? parseFloat(invitation.firstPaymentAmount).toFixed(2) : null, rewardAmountRmb: totalRewardRmb.toFixed(2),
rewardAmount: invitation.rewardAmount ? parseFloat(invitation.rewardAmount).toFixed(2) : null, rewardAmountPeso: totalRewardPeso.toFixed(2),
rewardStatus: invitation.rewardStatus, // Legacy field for backward compatibility
rewardAmount: (totalRewardRmb + totalRewardPeso).toFixed(2),
rewardStatus: hasPaid ? 'credited' : 'pending',
createdAt: invitation.createdAt, createdAt: invitation.createdAt,
})); };
})
);
return { return {
records, records,

View File

@ -98,8 +98,8 @@ const createPaymentOrder = async (data, adminId) => {
exists = !!existingOrder; exists = !!existingOrder;
} }
// Calculate total amount for commission (use RMB if available) // Calculate total amount for commission (check any currency)
const totalAmountForCommission = rmbAmount > 0 ? rmbAmount : legacyAmount; const totalAmountForCommission = rmbAmount > 0 ? rmbAmount : (pesoAmount > 0 ? pesoAmount : legacyAmount);
// Create payment order // Create payment order
const paymentOrder = await PaymentOrder.create({ const paymentOrder = await PaymentOrder.create({
@ -116,7 +116,7 @@ const createPaymentOrder = async (data, adminId) => {
status: 'active', status: 'active',
}); });
// Calculate commission (if applicable, based on RMB amount) // Calculate commission (if applicable, for any currency)
let commission = null; let commission = null;
if (totalAmountForCommission > 0) { if (totalAmountForCommission > 0) {
try { try {

View File

@ -124,8 +124,8 @@
<text class="table-cell">{{ item.uid }}</text> <text class="table-cell">{{ item.uid }}</text>
<text class="table-cell">{{ item.time }}</text> <text class="table-cell">{{ item.time }}</text>
<view class="table-cell status-cell"> <view class="table-cell status-cell">
<text v-if="item.paid && item.amount" class="paid-amount">¥{{ item.amount }}</text> <text class="paid-amount">¥{{ (item.rewardRmb || 0).toFixed(2) }}</text>
<text v-else class="unpaid-text">¥0</text> <text class="paid-amount peso">{{ (item.rewardPeso || 0).toFixed(2) }}</text>
</view> </view>
</view> </view>
</view> </view>
@ -468,13 +468,20 @@
console.log('GetInvitationRecords response:', res) console.log('GetInvitationRecords response:', res)
// : { code: 0, message: "", data: { records: [...] } } // : { code: 0, message: "", data: { records: [...] } }
if (res && res.code === 0 && res.data && res.data.records) { if (res && res.code === 0 && res.data && res.data.records) {
this.inviteRecords = res.data.records.map(item => ({ this.inviteRecords = res.data.records.map(item => {
const rewardRmb = parseFloat(item.rewardAmountRmb || 0)
const rewardPeso = parseFloat(item.rewardAmountPeso || 0)
return {
username: item.invitee?.nickname || '-', username: item.invitee?.nickname || '-',
uid: item.invitee?.uid || '-', uid: item.invitee?.uid || '-',
time: this.formatDate(item.createdAt), time: this.formatDate(item.createdAt),
paid: item.firstPaymentAt != null, paid: item.firstPaymentAt != null,
rewardRmb: rewardRmb,
rewardPeso: rewardPeso,
// Legacy field
amount: item.rewardAmount ? parseFloat(item.rewardAmount) : 0 amount: item.rewardAmount ? parseFloat(item.rewardAmount) : 0
})) }
})
} }
} catch (error) { } catch (error) {
console.error('获取邀请记录失败:', error) console.error('获取邀请记录失败:', error)
@ -1305,13 +1312,18 @@
&.status-cell { &.status-cell {
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.paid-amount { .paid-amount {
font-size: 28rpx; font-size: 26rpx;
font-weight: bold; font-weight: bold;
color: #333333; color: #FF3B4E;
&.peso {
color: #67c23a;
}
} }
.unpaid-text { .unpaid-text {