feat: 重构充值提现功能,添加冷钱包管理

后端改动:
- 新增冷钱包管理模块(ColdWallet实体、Mapper、Service、Controller)
- 充值流程:创建订单→显示钱包地址→用户确认打款→管理员审核
- 提现流程:用户输入地址和联系方式→冻结余额→管理员审核
- OrderFund新增字段:walletId, walletAddress, withdrawContact, payTime, confirmTime

前端改动(monisuo-admin):
- 新增冷钱包管理页面(wallets.vue)
- 优化订单管理页面,支持新的状态流转
- 添加调试日志帮助排查登录问题

前端改动(flutter_monisuo):
- 更新OrderFund模型支持新字段
- 充值成功后显示钱包地址弹窗
- 提现时收集提现地址和联系方式
- 新增资金订单页面

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
sion
2026-03-22 23:15:23 +08:00
parent a476d0a23b
commit 91227b7e51
21 changed files with 2225 additions and 229 deletions

View File

@@ -72,25 +72,39 @@ class OrderFund {
final int id;
final String orderNo;
final int userId;
final int orderType; // 1=充值, 2=提现
final String username;
final int type; // 1=充值, 2=提现
final String amount;
final int status; // 1=待审核, 2=已通过, 3=已拒绝, 4=已取消
final int status;
// 充值状态: 1=待付款, 2=待确认, 3=已完成, 4=已驳回, 5=已取消
// 提现状态: 1=待审批, 2=已完成, 3=已驳回, 4=已取消
final int? walletId; // 冷钱包ID(充值)
final String? walletAddress; // 钱包地址(充值/提现)
final String? withdrawContact; // 提现联系方式
final String remark;
final String? auditRemark;
final String? rejectReason;
final String? adminRemark;
final DateTime? createTime;
final DateTime? auditTime;
final DateTime? payTime; // 用户确认打款时间
final DateTime? confirmTime; // 管理员确认时间
OrderFund({
required this.id,
required this.orderNo,
required this.userId,
required this.orderType,
required this.username,
required this.type,
required this.amount,
required this.status,
this.walletId,
this.walletAddress,
this.withdrawContact,
required this.remark,
this.auditRemark,
this.rejectReason,
this.adminRemark,
this.createTime,
this.auditTime,
this.payTime,
this.confirmTime,
});
factory OrderFund.fromJson(Map<String, dynamic> json) {
@@ -98,42 +112,117 @@ class OrderFund {
id: json['id'] as int? ?? 0,
orderNo: json['orderNo'] as String? ?? '',
userId: json['userId'] as int? ?? 0,
orderType: json['orderType'] as int? ?? 1,
username: json['username'] as String? ?? '',
type: json['type'] as int? ?? 1,
amount: json['amount']?.toString() ?? '0.00',
status: json['status'] as int? ?? 1,
walletId: json['walletId'] as int?,
walletAddress: json['walletAddress'] as String?,
withdrawContact: json['withdrawContact'] as String?,
remark: json['remark']?.toString() ?? '',
auditRemark: json['auditRemark']?.toString(),
rejectReason: json['rejectReason'] as String?,
adminRemark: json['adminRemark'] as String?,
createTime: json['createTime'] != null
? DateTime.tryParse(json['createTime'])
: null,
auditTime: json['auditTime'] != null
? DateTime.tryParse(json['auditTime'])
payTime: json['payTime'] != null
? DateTime.tryParse(json['payTime'])
: null,
confirmTime: json['confirmTime'] != null
? DateTime.tryParse(json['confirmTime'])
: null,
);
}
/// 订单类型文字
String get orderTypeText => orderType == 1 ? '充值' : '提现';
String get typeText => type == 1 ? '充值' : '提现';
/// 状态文字
/// 状态文字 (根据类型区分)
String get statusText {
switch (status) {
case 1:
return '待审核';
case 2:
return '已通过';
case 3:
return '已拒绝';
case 4:
return '取消';
default:
return '未知';
if (type == 1) {
// 充值状态
switch (status) {
case 1:
return '待付款';
case 2:
return '待确认';
case 3:
return '完成';
case 4:
return '已驳回';
case 5:
return '已取消';
default:
return '未知';
}
} else {
// 提现状态
switch (status) {
case 1:
return '待审批';
case 2:
return '已完成';
case 3:
return '已驳回';
case 4:
return '已取消';
default:
return '未知';
}
}
}
/// 是否为充值
bool get isDeposit => orderType == 1;
bool get isDeposit => type == 1;
/// 是否可取消
bool get canCancel => status == 1;
/// 充值: 仅待付款可取消
/// 提现: 仅待审批可取消
bool get canCancel {
if (type == 1) {
return status == 1; // 充值待付款
} else {
return status == 1; // 提现待审批
}
}
/// 是否可确认打款 (仅充值待付款)
bool get canConfirmPay => type == 1 && status == 1;
}
/// 冷钱包模型
class ColdWallet {
final int id;
final String name;
final String address;
final String network;
final bool isDefault;
final int status; // 0=禁用, 1=启用
final DateTime? createTime;
ColdWallet({
required this.id,
required this.name,
required this.address,
required this.network,
required this.isDefault,
required this.status,
this.createTime,
});
factory ColdWallet.fromJson(Map<String, dynamic> json) {
return ColdWallet(
id: json['id'] as int? ?? 0,
name: json['name'] as String? ?? '',
address: json['address'] as String? ?? '',
network: json['network'] as String? ?? 'TRC20',
isDefault: json['isDefault'] as bool? ?? false,
status: json['status'] as int? ?? 1,
createTime: json['createTime'] != null
? DateTime.tryParse(json['createTime'])
: null,
);
}
bool get isEnabled => status == 1;
}