This commit is contained in:
sion
2026-04-05 23:28:38 +08:00
parent 0c66b3725f
commit da0f9d6f5e
21 changed files with 640 additions and 394 deletions

View File

@@ -8,11 +8,13 @@ import com.it.rattan.monisuo.context.UserContext;
import com.it.rattan.monisuo.entity.*;
import com.it.rattan.monisuo.mapper.AccountFundMapper;
import com.it.rattan.monisuo.mapper.OrderFundMapper;
import com.it.rattan.monisuo.mapper.OrderTradeMapper;
import com.it.rattan.monisuo.service.*;
import com.it.rattan.monisuo.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
@@ -46,6 +48,9 @@ public class AdminController {
@Autowired
private OrderFundMapper orderFundMapper;
@Autowired
private OrderTradeMapper orderTradeMapper;
// ==================== 公开接口 ====================
/**
@@ -451,7 +456,7 @@ public class AdminController {
}
/**
* 资金总览
* 资金总览(看板专用,一次 API 返回所有数据)
*/
@GetMapping("/finance/overview")
public Result<Map<String, Object>> getFinanceOverview() {
@@ -461,21 +466,47 @@ public class AdminController {
Map<String, Object> data = new HashMap<>();
// 合并为一次查询获取充值总额、提现总额、待审批数
Map<String, Object> fundStats = orderFundMapper.sumFinanceOverview();
// 本月和上月时间范围(用于环比)
LocalDate today = LocalDate.now();
LocalDateTime monthStart = today.withDayOfMonth(1).atStartOfDay();
LocalDateTime monthEnd = today.plusMonths(1).withDayOfMonth(1).atStartOfDay();
LocalDateTime lastMonthStart = today.minusMonths(1).withDayOfMonth(1).atStartOfDay();
LocalDateTime lastMonthEnd = monthStart;
// 查询1order_fund 一次聚合(充值总额、提现总额、实际出款、待审批、环比)
Map<String, Object> fundStats = orderFundMapper.sumDashboardStats(
monthStart, monthEnd, lastMonthStart, lastMonthEnd);
data.put("totalDeposit", fundStats.get("totalDeposit"));
data.put("totalWithdraw", fundStats.get("totalWithdraw"));
data.put("totalActualPayout", fundStats.get("totalActualPayout"));
data.put("pendingCount", ((Number) fundStats.get("pendingCount")).intValue());
data.put("monthlyDeposit", fundStats.get("monthlyDeposit"));
data.put("monthlyWithdraw", fundStats.get("monthlyWithdraw"));
data.put("lastMonthDeposit", fundStats.get("lastMonthDeposit"));
data.put("lastMonthWithdraw", fundStats.get("lastMonthWithdraw"));
BigDecimal fundBalance = accountFundMapper.sumAllBalance();
data.put("fundBalance", fundBalance);
// 查询2account_fund 余额和冻结
Map<String, Object> balanceStats = accountFundMapper.sumBalanceAndFrozen();
data.put("fundBalance", balanceStats.get("totalBalance"));
data.put("totalFrozen", balanceStats.get("totalFrozen"));
// 查询3交易账户市值
BigDecimal tradeValue = accountFundMapper.sumAllTradeValue();
data.put("tradeValue", tradeValue != null ? tradeValue : BigDecimal.ZERO);
// 查询4用户统计
long userCount = userService.count();
data.put("userCount", userCount);
int monthNewUsers = userService.count(new LambdaQueryWrapper<User>()
.ge(User::getCreateTime, monthStart));
data.put("monthNewUsers", monthNewUsers);
// 查询5今日活跃用户今日有过交易的独立用户数
int todayActiveUsers = orderTradeMapper.countDistinctUserByTime(
today.atStartOfDay(), LocalDateTime.now());
data.put("todayActiveUsers", todayActiveUsers);
return Result.success(data);
}

View File

@@ -135,4 +135,13 @@ public class ColdWalletController {
result.put("network", wallet.getNetwork());
return Result.success(result);
}
/**
* 用户端 - 获取可用的提现网络列表
*/
@GetMapping("/api/wallet/networks")
public Result<List<String>> getNetworks() {
List<String> networks = coldWalletService.getEnabledNetworks();
return Result.success(networks);
}
}

View File

@@ -87,6 +87,7 @@ public class FundController {
BigDecimal amount = request.getAmount();
String withdrawAddress = request.getWithdrawAddress();
String network = request.getNetwork();
String withdrawContact = request.getWithdrawContact();
String remark = request.getRemark();
@@ -99,7 +100,7 @@ public class FundController {
}
try {
Map<String, Object> result = fundService.withdraw(userId, amount, withdrawAddress, withdrawContact, remark);
Map<String, Object> result = fundService.withdraw(userId, amount, withdrawAddress, network, withdrawContact, remark);
return Result.success("申请成功,等待审批", result);
} catch (Exception e) {
return Result.fail(e.getMessage());

View File

@@ -12,6 +12,7 @@ import java.math.BigDecimal;
public class WithdrawRequest {
private BigDecimal amount;
private String withdrawAddress;
private String network;
private String withdrawContact;
private String remark;
}

View File

@@ -47,6 +47,9 @@ public class OrderFund implements Serializable {
/** 冷钱包地址(充值)/提现地址 */
private String walletAddress;
/** 提现网络类型(TRC20/ERC20等) */
private String network;
/** 提现联系方式 */
private String withdrawContact;

View File

@@ -5,6 +5,7 @@ import com.it.rattan.monisuo.entity.AccountFund;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.math.BigDecimal;
import java.util.Map;
/**
* 资金账户Mapper
@@ -15,6 +16,12 @@ public interface AccountFundMapper extends BaseMapper<AccountFund> {
@Select("SELECT IFNULL(SUM(balance), 0) FROM account_fund")
BigDecimal sumAllBalance();
/**
* 一次查询获取总余额和总冻结金额
*/
@Select("SELECT IFNULL(SUM(balance), 0) as totalBalance, IFNULL(SUM(frozen), 0) as totalFrozen FROM account_fund")
Map<String, Object> sumBalanceAndFrozen();
@Select("SELECT IFNULL(SUM(total_deposit), 0) FROM account_fund")
BigDecimal sumTotalDeposit();

View File

@@ -16,31 +16,34 @@ import java.util.Map;
@Mapper
public interface OrderFundMapper extends BaseMapper<OrderFund> {
@Select("SELECT IFNULL(SUM(amount), 0) FROM order_fund WHERE type = 1 AND status = 2")
BigDecimal sumCompletedDeposit();
@Select("SELECT IFNULL(SUM(amount), 0) FROM order_fund WHERE type = 2 AND status = 2")
BigDecimal sumCompletedWithdraw();
@Select("SELECT COUNT(*) FROM order_fund WHERE status = 1")
int countPending();
/**
* 一次性聚合查询:充值总额、提现总额、待审批数
* 一次性聚合查询:充值总额、提现总额、实际出款、待审批数、本月/上月环比数据
* 充值已完成 status=3提现已完成 status=2
*/
@Select("SELECT " +
"IFNULL(SUM(CASE WHEN type = 1 AND status = 2 THEN amount ELSE 0 END), 0) as totalDeposit, " +
"IFNULL(SUM(CASE WHEN type = 1 AND status = 3 THEN amount ELSE 0 END), 0) as totalDeposit, " +
"IFNULL(SUM(CASE WHEN type = 2 AND status = 2 THEN amount ELSE 0 END), 0) as totalWithdraw, " +
"SUM(CASE WHEN status IN (1, 5) THEN 1 ELSE 0 END) as pendingCount " +
"IFNULL(SUM(CASE WHEN type = 2 AND status = 2 THEN IFNULL(receivable_amount, amount * 0.9) ELSE 0 END), 0) as totalActualPayout, " +
"SUM(CASE WHEN (type = 1 AND status = 2) OR (type = 2 AND status IN (1, 5)) THEN 1 ELSE 0 END) as pendingCount, " +
"IFNULL(SUM(CASE WHEN type = 1 AND status = 3 AND create_time >= #{monthStart} AND create_time < #{monthEnd} THEN amount ELSE 0 END), 0) as monthlyDeposit, " +
"IFNULL(SUM(CASE WHEN type = 2 AND status = 2 AND create_time >= #{monthStart} AND create_time < #{monthEnd} THEN amount ELSE 0 END), 0) as monthlyWithdraw, " +
"IFNULL(SUM(CASE WHEN type = 1 AND status = 3 AND create_time >= #{lastMonthStart} AND create_time < #{lastMonthEnd} THEN amount ELSE 0 END), 0) as lastMonthDeposit, " +
"IFNULL(SUM(CASE WHEN type = 2 AND status = 2 AND create_time >= #{lastMonthStart} AND create_time < #{lastMonthEnd} THEN amount ELSE 0 END), 0) as lastMonthWithdraw " +
"FROM order_fund")
Map<String, Object> sumFinanceOverview();
Map<String, Object> sumDashboardStats(
@Param("monthStart") LocalDateTime monthStart,
@Param("monthEnd") LocalDateTime monthEnd,
@Param("lastMonthStart") LocalDateTime lastMonthStart,
@Param("lastMonthEnd") LocalDateTime lastMonthEnd);
// ========== 分析相关查询 ==========
/**
* 指定时间段内的手续费总额0.5%
* 充值已完成 status=3提现已完成 status=2
*/
@Select("SELECT IFNULL(SUM(amount * 0.005), 0) FROM order_fund WHERE status = 2 AND create_time >= #{startTime}")
@Select("SELECT IFNULL(SUM(amount * 0.005), 0) FROM order_fund WHERE " +
"((type = 1 AND status = 3) OR (type = 2 AND status = 2)) AND create_time >= #{startTime}")
BigDecimal sumFeeByTime(@Param("startTime") LocalDateTime startTime);
/**
@@ -58,9 +61,10 @@ public interface OrderFundMapper extends BaseMapper<OrderFund> {
/**
* 按月分组统计充值/提现金额(替代循环 N 次查询)
* 充值已完成 status=3提现已完成 status=2
*/
@Select("SELECT DATE_FORMAT(create_time, '%Y-%m') as month, " +
"IFNULL(SUM(CASE WHEN type = 1 AND status = 2 THEN amount ELSE 0 END), 0) as deposit, " +
"IFNULL(SUM(CASE WHEN type = 1 AND status = 3 THEN amount ELSE 0 END), 0) as deposit, " +
"IFNULL(SUM(CASE WHEN type = 2 AND status = 2 THEN amount ELSE 0 END), 0) as withdraw " +
"FROM order_fund WHERE create_time >= #{startTime} AND create_time < #{endTime} " +
"GROUP BY DATE_FORMAT(create_time, '%Y-%m') ORDER BY month")

View File

@@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
/**
* 冷钱包地址服务
@@ -28,6 +29,18 @@ public class ColdWalletService {
return coldWalletMapper.selectList(wrapper);
}
/**
* 获取所有启用的网络类型(去重)
*/
public List<String> getEnabledNetworks() {
List<ColdWallet> wallets = getEnabledList();
return wallets.stream()
.map(ColdWallet::getNetwork)
.filter(n -> n != null && !n.isEmpty())
.distinct()
.collect(Collectors.toList());
}
/**
* 获取启用的钱包列表
*/

View File

@@ -25,7 +25,7 @@ import java.util.*;
*
* 状态定义:
* 充值: 1=待付款, 2=待确认, 3=已完成, 4=已驳回, 5=已取消
* 提现: 1=待审批, 2=已完成, 3=已驳回, 4=已取消
* 提现: 1=待审批, 2=已出款, 3=已驳回, 4=已取消
*
* 审批参数说明:
* status=2 表示审批通过充值订单最终状态为3提现订单最终状态为2
@@ -128,7 +128,7 @@ public class FundService {
*/
@Transactional
public Map<String, Object> withdraw(Long userId, BigDecimal amount, String withdrawAddress,
String withdrawContact, String remark) {
String network, String withdrawContact, String remark) {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new RuntimeException("提现金额必须大于0");
}
@@ -200,6 +200,7 @@ public class FundService {
order.setReceivableAmount(receivableAmount);
order.setStatus(1); // 待审批
order.setWalletAddress(withdrawAddress);
order.setNetwork(network);
order.setWithdrawContact(withdrawContact);
order.setRemark(remark);
order.setCreateTime(LocalDateTime.now());