新人
This commit is contained in:
parent
2e90b3e4b2
commit
b25822aa61
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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' },
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user