111
This commit is contained in:
@@ -254,6 +254,25 @@ public class AdminController {
|
||||
return Result.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户统计数据(管理后台详情面板)
|
||||
*/
|
||||
@GetMapping("/user/stats")
|
||||
public Result<Map<String, Object>> getUserStats(@RequestParam Long userId) {
|
||||
if (!UserContext.isSuperAdmin()) {
|
||||
return Result.fail("无权限访问");
|
||||
}
|
||||
|
||||
User user = userService.getById(userId);
|
||||
if (user == null) {
|
||||
return Result.fail("用户不存在");
|
||||
}
|
||||
|
||||
Map<String, Object> stats = assetService.getUserStats(userId);
|
||||
stats.put("user", user);
|
||||
return Result.success(stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用/启用用户
|
||||
*/
|
||||
|
||||
@@ -5,11 +5,15 @@ import com.it.rattan.monisuo.entity.AccountFlow;
|
||||
import com.it.rattan.monisuo.entity.AccountFund;
|
||||
import com.it.rattan.monisuo.entity.AccountTrade;
|
||||
import com.it.rattan.monisuo.entity.Coin;
|
||||
import com.it.rattan.monisuo.entity.OrderFund;
|
||||
import com.it.rattan.monisuo.entity.OrderTrade;
|
||||
import com.it.rattan.monisuo.entity.User;
|
||||
import com.it.rattan.monisuo.mapper.AccountFlowMapper;
|
||||
import com.it.rattan.monisuo.mapper.AccountFundMapper;
|
||||
import com.it.rattan.monisuo.mapper.AccountTradeMapper;
|
||||
import com.it.rattan.monisuo.mapper.OrderFundMapper;
|
||||
import com.it.rattan.monisuo.mapper.OrderTradeMapper;
|
||||
import com.it.rattan.monisuo.mapper.UserMapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.it.rattan.monisuo.util.OrderNoUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -44,6 +48,12 @@ public class AssetService {
|
||||
@Autowired
|
||||
private AccountFlowMapper accountFlowMapper;
|
||||
|
||||
@Autowired
|
||||
private OrderFundMapper orderFundMapper;
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private CoinService coinService;
|
||||
|
||||
@@ -379,4 +389,142 @@ public class AssetService {
|
||||
result.put("totalProfit", totalProfit);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户统计数据(管理后台用)
|
||||
*/
|
||||
public Map<String, Object> getUserStats(Long userId) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
// 1. 资金账户
|
||||
AccountFund fund = getOrCreateFundAccount(userId);
|
||||
Map<String, Object> fundAccount = new HashMap<>();
|
||||
fundAccount.put("balance", fund.getBalance());
|
||||
fundAccount.put("frozen", fund.getFrozen());
|
||||
fundAccount.put("totalDeposit", fund.getTotalDeposit());
|
||||
fundAccount.put("totalWithdraw", fund.getTotalWithdraw());
|
||||
result.put("fundAccount", fundAccount);
|
||||
|
||||
// 2. 交易账户持仓
|
||||
result.put("tradeAccounts", getTradeAccount(userId));
|
||||
|
||||
// 3. 充提统计(一次查询按类型分组,避免两次查询)
|
||||
LambdaQueryWrapper<OrderFund> fundOrderWrapper = new LambdaQueryWrapper<>();
|
||||
fundOrderWrapper.eq(OrderFund::getUserId, userId);
|
||||
List<OrderFund> allFundOrders = orderFundMapper.selectList(fundOrderWrapper);
|
||||
|
||||
List<OrderFund> allDeposits = allFundOrders.stream()
|
||||
.filter(o -> o.getType() == 1).collect(Collectors.toList());
|
||||
List<OrderFund> allWithdraws = allFundOrders.stream()
|
||||
.filter(o -> o.getType() == 2).collect(Collectors.toList());
|
||||
|
||||
Map<String, Object> depositStats = new HashMap<>();
|
||||
depositStats.put("totalCount", allDeposits.size());
|
||||
depositStats.put("totalAmount", allDeposits.stream().map(OrderFund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
depositStats.put("successCount", allDeposits.stream().filter(o -> o.getStatus() == 3).count());
|
||||
depositStats.put("successAmount", allDeposits.stream().filter(o -> o.getStatus() == 3).map(OrderFund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
result.put("depositStats", depositStats);
|
||||
|
||||
Map<String, Object> withdrawStats = new HashMap<>();
|
||||
withdrawStats.put("totalCount", allWithdraws.size());
|
||||
withdrawStats.put("totalAmount", allWithdraws.stream().map(OrderFund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
withdrawStats.put("successCount", allWithdraws.stream().filter(o -> o.getStatus() == 2).count());
|
||||
withdrawStats.put("successAmount", allWithdraws.stream().filter(o -> o.getStatus() == 2).map(OrderFund::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
withdrawStats.put("totalFee", allWithdraws.stream().filter(o -> o.getStatus() == 2).map(o -> o.getFee() != null ? o.getFee() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
result.put("withdrawStats", withdrawStats);
|
||||
|
||||
// 5. 推广统计(优化:批量查询消除 N+1)
|
||||
// 直接推广人(referredBy = userId)
|
||||
LambdaQueryWrapper<User> referralWrapper = new LambdaQueryWrapper<>();
|
||||
referralWrapper.eq(User::getReferredBy, userId)
|
||||
.orderByDesc(User::getCreateTime);
|
||||
List<User> directReferrals = userMapper.selectList(referralWrapper);
|
||||
List<Long> directIds = directReferrals.stream().map(User::getId).collect(Collectors.toList());
|
||||
|
||||
// 间接推广人:一次 IN 查询
|
||||
long indirectCount = 0;
|
||||
if (!directIds.isEmpty()) {
|
||||
LambdaQueryWrapper<User> indirectWrapper = new LambdaQueryWrapper<>();
|
||||
indirectWrapper.in(User::getReferredBy, directIds);
|
||||
indirectCount = userMapper.selectCount(indirectWrapper);
|
||||
}
|
||||
|
||||
// 批量查询直接推广人是否已充值(一次 IN 查询)
|
||||
Set<Long> depositedUserIds = new HashSet<>();
|
||||
if (!directIds.isEmpty()) {
|
||||
LambdaQueryWrapper<OrderFund> batchDepositWrapper = new LambdaQueryWrapper<>();
|
||||
batchDepositWrapper.in(OrderFund::getUserId, directIds)
|
||||
.eq(OrderFund::getType, 1).eq(OrderFund::getStatus, 3)
|
||||
.select(OrderFund::getUserId)
|
||||
.groupBy(OrderFund::getUserId);
|
||||
orderFundMapper.selectList(batchDepositWrapper)
|
||||
.forEach(o -> depositedUserIds.add(o.getUserId()));
|
||||
}
|
||||
|
||||
List<Map<String, Object>> referralList = new ArrayList<>();
|
||||
for (User ref : directReferrals) {
|
||||
Map<String, Object> refInfo = new HashMap<>();
|
||||
refInfo.put("userId", ref.getId());
|
||||
refInfo.put("username", ref.getUsername());
|
||||
refInfo.put("nickname", ref.getNickname());
|
||||
refInfo.put("createTime", ref.getCreateTime());
|
||||
refInfo.put("deposited", depositedUserIds.contains(ref.getId()));
|
||||
referralList.add(refInfo);
|
||||
}
|
||||
Map<String, Object> referralStats = new HashMap<>();
|
||||
referralStats.put("directCount", directReferrals.size());
|
||||
referralStats.put("indirectCount", indirectCount);
|
||||
referralStats.put("referrals", referralList);
|
||||
result.put("referralStats", referralStats);
|
||||
|
||||
// 6. 福利统计(从 account_flow 查询福利类型记录)
|
||||
LambdaQueryWrapper<AccountFlow> bonusWrapper = new LambdaQueryWrapper<>();
|
||||
bonusWrapper.eq(AccountFlow::getUserId, userId)
|
||||
.eq(AccountFlow::getFlowType, 7)
|
||||
.orderByDesc(AccountFlow::getCreateTime);
|
||||
List<AccountFlow> bonusFlows = accountFlowMapper.selectList(bonusWrapper);
|
||||
BigDecimal totalBonusClaimed = bonusFlows.stream()
|
||||
.map(AccountFlow::getAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
List<Map<String, Object>> bonusRecords = new ArrayList<>();
|
||||
for (AccountFlow flow : bonusFlows) {
|
||||
Map<String, Object> record = new HashMap<>();
|
||||
String remark = flow.getRemark() != null ? flow.getRemark() : "福利";
|
||||
String type;
|
||||
if (remark.startsWith("新人首充")) {
|
||||
type = "新人首充福利";
|
||||
} else if (remark.startsWith("间接推广")) {
|
||||
type = "间接推广奖励";
|
||||
} else if (remark.startsWith("邀请奖励")) {
|
||||
type = "直接推广奖励";
|
||||
} else {
|
||||
type = remark;
|
||||
}
|
||||
record.put("type", type);
|
||||
record.put("amount", flow.getAmount());
|
||||
record.put("time", flow.getCreateTime());
|
||||
bonusRecords.add(record);
|
||||
}
|
||||
Map<String, Object> bonusStats = new HashMap<>();
|
||||
bonusStats.put("totalBonusClaimed", totalBonusClaimed);
|
||||
bonusStats.put("totalBonusCount", bonusFlows.size());
|
||||
bonusStats.put("records", bonusRecords);
|
||||
result.put("bonusStats", bonusStats);
|
||||
|
||||
// 7. 最近充提订单(最近20笔)
|
||||
LambdaQueryWrapper<OrderFund> recentOrderWrapper = new LambdaQueryWrapper<>();
|
||||
recentOrderWrapper.eq(OrderFund::getUserId, userId)
|
||||
.orderByDesc(OrderFund::getCreateTime)
|
||||
.last("LIMIT 20");
|
||||
result.put("recentFundOrders", orderFundMapper.selectList(recentOrderWrapper));
|
||||
|
||||
// 8. 最近交易订单(最近20笔)
|
||||
LambdaQueryWrapper<OrderTrade> recentTradeWrapper = new LambdaQueryWrapper<>();
|
||||
recentTradeWrapper.eq(OrderTrade::getUserId, userId)
|
||||
.orderByDesc(OrderTrade::getCreateTime)
|
||||
.last("LIMIT 20");
|
||||
result.put("recentTradeOrders", orderTradeMapper.selectList(recentTradeWrapper));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user