初始化
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
class ApcApiModel {
|
||||
String? bank;
|
||||
bool? validated;
|
||||
String? cardType;
|
||||
String? key;
|
||||
List<dynamic>? messages;
|
||||
String? stat;
|
||||
|
||||
static ApcApiModel? fromMap(Map<String, dynamic>? map) {
|
||||
if (map == null) return null;
|
||||
ApcApiModel apcApiModel = ApcApiModel();
|
||||
apcApiModel.bank = map['bank'];
|
||||
apcApiModel.validated = map['validated'];
|
||||
apcApiModel.cardType = map['cardType'];
|
||||
apcApiModel.key = map['key'];
|
||||
apcApiModel.messages = map['messages'];
|
||||
apcApiModel.stat = map['stat'];
|
||||
return apcApiModel;
|
||||
}
|
||||
|
||||
Map toJson() => {
|
||||
"bank": bank,
|
||||
"validated": validated,
|
||||
"cardType": cardType,
|
||||
"key": key,
|
||||
"messages": messages,
|
||||
"stat": stat,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
class WithdrawConfig {
|
||||
WithdrawConfig({
|
||||
this.channels,
|
||||
this.id,
|
||||
this.cashTax,
|
||||
this.coinTax,
|
||||
this.gameTax,
|
||||
});
|
||||
|
||||
List<Channel>? channels;
|
||||
int? id;
|
||||
int? cashTax;
|
||||
int? coinTax;
|
||||
int? gameTax;
|
||||
|
||||
Channel? get getBankCardChannel {
|
||||
for (Channel item in (channels ?? [])) {
|
||||
if (item.isBankCard) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Channel> get realChannel {
|
||||
final channel_ = <Channel>[];
|
||||
|
||||
if (getBankCardChannel != null) {
|
||||
channel_.add(getBankCardChannel!);
|
||||
}
|
||||
|
||||
if (getUsdtChannel != null) {
|
||||
channel_.add(getUsdtChannel!);
|
||||
}
|
||||
|
||||
return channel_;
|
||||
}
|
||||
|
||||
Channel? get getUsdtChannel {
|
||||
for (Channel item in (channels ?? [])) {
|
||||
if (item.isUsdt) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool get hasBankCard {
|
||||
for (Channel item in (channels ?? [])) {
|
||||
if (item.isBankCard) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool get hasUsdt {
|
||||
for (Channel item in (channels ?? [])) {
|
||||
if (item.isUsdt) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
factory WithdrawConfig.fromJson(Map<String, dynamic> json) => WithdrawConfig(
|
||||
channels: List<Channel>.from(json["channels"].map((x) => Channel.fromJson(x))),
|
||||
id: json["ID"],
|
||||
cashTax: json["cashTax"],
|
||||
coinTax: json["coinTax"],
|
||||
gameTax: json["gameTax"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"channels": channels == null ? [] : List<dynamic>.from(channels!.map((x) => x.toJson())),
|
||||
"ID": id,
|
||||
"cashTax": cashTax,
|
||||
"coinTax": coinTax,
|
||||
"gameTax": gameTax,
|
||||
};
|
||||
}
|
||||
|
||||
class Channel {
|
||||
Channel({
|
||||
this.channelName,
|
||||
this.cid,
|
||||
this.payType,
|
||||
this.minMoney,
|
||||
this.maxMoney,
|
||||
this.qpMinMoney,
|
||||
this.qpMaxMoney,
|
||||
});
|
||||
|
||||
String? channelName;
|
||||
String? cid;
|
||||
String? payType;
|
||||
int? minMoney;
|
||||
int? maxMoney;
|
||||
int? qpMinMoney;
|
||||
int? qpMaxMoney;
|
||||
bool get isBankCard => payType?.toLowerCase() == "bankcard";
|
||||
bool get isUsdt => payType?.toLowerCase() == "usdt";
|
||||
|
||||
factory Channel.fromJson(Map<String, dynamic> json) => Channel(
|
||||
channelName: json["channelName"],
|
||||
cid: json["cid"],
|
||||
payType: json["payType"],
|
||||
minMoney: json["minMoney"],
|
||||
maxMoney: json["maxMoney"],
|
||||
qpMinMoney: json["qpMinMoney"],
|
||||
qpMaxMoney: json["qpMaxMoney"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"channelName": channelName,
|
||||
"cid": cid,
|
||||
"payType": payType,
|
||||
"minMoney": minMoney,
|
||||
"maxMoney": maxMoney,
|
||||
"qpMinMoney": qpMinMoney,
|
||||
"qpMaxMoney": qpMaxMoney,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/hj_utils/api_service/mine_service.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
|
||||
import 'mine_withdrawal_record_page.dart';
|
||||
import 'widget/record_list_item.dart';
|
||||
import 'withdraw_details_model.dart';
|
||||
|
||||
abstract class MineWithdrawalRecordLogic extends GetxController {
|
||||
RefreshController? refreshController;
|
||||
int page = 1;
|
||||
|
||||
WithdrawDetailsModel? withdrawDetailsModel;
|
||||
final dataSource = [];
|
||||
bool isLoading = true;
|
||||
|
||||
@override
|
||||
onReady() {
|
||||
super.onReady();
|
||||
fetchPageData();
|
||||
}
|
||||
|
||||
@mustCallSuper
|
||||
fetchPageData({bool isRefresh = true}) async {
|
||||
if (isRefresh) page = 1;
|
||||
}
|
||||
|
||||
Widget instanceChildItem(int index);
|
||||
}
|
||||
|
||||
//提现明细
|
||||
class WithDrawalRecordController extends MineWithdrawalRecordLogic {
|
||||
@override
|
||||
fetchPageData({bool isRefresh = true}) async {
|
||||
super.fetchPageData(isRefresh: isRefresh);
|
||||
|
||||
final result =
|
||||
await MineService.getWithdrawDetails(pageNumber: page, pageSize: 10);
|
||||
isLoading = false;
|
||||
|
||||
if (isRefresh) {
|
||||
dataSource.clear();
|
||||
refreshController?.refreshCompleted();
|
||||
}
|
||||
result?.hasNext ?? false
|
||||
? refreshController?.loadComplete()
|
||||
: refreshController?.loadNoData();
|
||||
dataSource.addAll(result?.list ?? []);
|
||||
page += 1;
|
||||
update();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget instanceChildItem(int index) {
|
||||
return WithdrawalRecordItem(dataSource[index]);
|
||||
}
|
||||
}
|
||||
|
||||
//金币订单明细
|
||||
class GoldBillRecordController extends MineWithdrawalRecordLogic {
|
||||
@override
|
||||
fetchPageData({bool isRefresh = true}) async {
|
||||
super.fetchPageData(isRefresh: isRefresh);
|
||||
final res = await MineService.getBillData(
|
||||
pageSize: 15,
|
||||
pageNumber: page,
|
||||
type: 1,
|
||||
);
|
||||
isLoading = false;
|
||||
if (isRefresh) {
|
||||
dataSource.clear();
|
||||
refreshController?.refreshCompleted();
|
||||
}
|
||||
res?.hasNext ?? false
|
||||
? refreshController?.loadComplete()
|
||||
: refreshController?.loadNoData();
|
||||
dataSource.addAll(res?.list ?? []);
|
||||
page += 1;
|
||||
update();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget instanceChildItem(int index) {
|
||||
return GoldRecordItem(dataSource[index]);
|
||||
}
|
||||
}
|
||||
|
||||
//充值明细
|
||||
class RechargeRecordController extends MineWithdrawalRecordLogic {
|
||||
@override
|
||||
fetchPageData({bool isRefresh = true}) async {
|
||||
super.fetchPageData(isRefresh: isRefresh);
|
||||
final res =
|
||||
await MineService.getRechargeBill(pageNumber: page, pageSize: 15);
|
||||
isLoading = false;
|
||||
if (isRefresh) {
|
||||
dataSource.clear();
|
||||
refreshController?.refreshCompleted();
|
||||
}
|
||||
res?.hasNext ?? false
|
||||
? refreshController?.loadComplete()
|
||||
: refreshController?.loadNoData();
|
||||
dataSource.addAll(res?.list ?? []);
|
||||
page += 1;
|
||||
update();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget instanceChildItem(int index) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 14),
|
||||
child: RechargeRecordItem(dataSource[index]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//收益明细
|
||||
class IncomeRecordController extends MineWithdrawalRecordLogic {
|
||||
@override
|
||||
fetchPageData({bool isRefresh = true}) async {
|
||||
super.fetchPageData(isRefresh: isRefresh);
|
||||
final res =
|
||||
await MineService.getIncomeRecord(pageNumber: page, pageSize: 15);
|
||||
isLoading = false;
|
||||
if (isRefresh) {
|
||||
dataSource.clear();
|
||||
refreshController?.refreshCompleted();
|
||||
}
|
||||
res?.hasNext ?? false
|
||||
? refreshController?.loadComplete()
|
||||
: refreshController?.loadNoData();
|
||||
dataSource.addAll(res?.list ?? []);
|
||||
page += 1;
|
||||
update();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget instanceChildItem(int index) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 12),
|
||||
child: InComeRecordItem(dataSource[index]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MineWithdrawalRecordLogic instanceController(RecordType type) {
|
||||
switch (type) {
|
||||
case RecordType.bill:
|
||||
return GoldBillRecordController();
|
||||
case RecordType.withdraw:
|
||||
return WithDrawalRecordController();
|
||||
case RecordType.recharge:
|
||||
return RechargeRecordController();
|
||||
case RecordType.income:
|
||||
return IncomeRecordController();
|
||||
default:
|
||||
throw '$type 没有找到';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:hgdj/tools_base/refresh/pull_refresh.dart';
|
||||
|
||||
import 'mine_withdrawal_record_logic.dart';
|
||||
|
||||
enum RecordType {
|
||||
recharge('充值记录'),
|
||||
withdraw('提现明细'),
|
||||
bill('余额明细'),
|
||||
income('业绩明细');
|
||||
|
||||
final String title;
|
||||
const RecordType(this.title);
|
||||
}
|
||||
|
||||
//明细综合页面
|
||||
class RecordsPage extends StatefulWidget {
|
||||
final RecordType type; // 0:收益, 1: 提现
|
||||
const RecordsPage(this.type, {super.key});
|
||||
|
||||
@override
|
||||
State<RecordsPage> createState() => _RecordsPageState();
|
||||
}
|
||||
|
||||
class _RecordsPageState extends State<RecordsPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetBuilder<MineWithdrawalRecordLogic>(
|
||||
init: instanceController(widget.type),
|
||||
builder: (controller) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(widget.type.title)),
|
||||
body: pullYsRefresh(
|
||||
onRefresh: (refreshController) => controller.fetchPageData(),
|
||||
onLoading: (refreshController) =>
|
||||
controller.fetchPageData(isRefresh: false),
|
||||
onInit: (ctr) => controller.refreshController = ctr,
|
||||
child: () {
|
||||
if (controller.isLoading) return LoadingCenterWidget();
|
||||
if (controller.dataSource.isEmpty)
|
||||
return CErrorWidget(
|
||||
retryOnTap: () => controller.fetchPageData());
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: controller.dataSource.length,
|
||||
padding: EdgeInsets.only(top: 12, left: 16.w, right: 16.w),
|
||||
itemBuilder: (context, index) =>
|
||||
controller.instanceChildItem(index),
|
||||
);
|
||||
}(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hgdj/assets_tool/app_colors.dart';
|
||||
import 'package:hgdj/assets_tool/images.dart';
|
||||
import 'package:hgdj/extension/extensions.dart';
|
||||
import 'package:hgdj/hj_model/mine/exchange/bill_item_model.dart';
|
||||
import 'package:hgdj/hj_utils/date_time_util.dart';
|
||||
import 'package:hgdj/hj_utils/screen.dart';
|
||||
import 'package:hgdj/tools_base/toast.dart';
|
||||
|
||||
import '../withdraw_details_model.dart';
|
||||
|
||||
class GoldRecordItem extends StatelessWidget {
|
||||
final BillItemModel model;
|
||||
|
||||
const GoldRecordItem(this.model, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
12.sizeBoxH,
|
||||
Text(
|
||||
model.tranType ?? '',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
4.sizeBoxH,
|
||||
Text(
|
||||
model.desc ?? '',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .5),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
4.sizeBoxH,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
model.createdAt.utcToYMDHMS(),
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .5),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
Text(
|
||||
'${model.realCount}${model.unit}',
|
||||
style: const TextStyle(
|
||||
color: Color(0xffF68804),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
12.sizeBoxH,
|
||||
1.line,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//充值记录
|
||||
class RechargeRecordItem extends StatelessWidget {
|
||||
final ListBean model;
|
||||
|
||||
const RechargeRecordItem(this.model, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"${model.productName ?? ""}",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
2.sizeBoxH,
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () {
|
||||
///复制到剪切板
|
||||
Clipboard.setData(ClipboardData(text: model.orderId ?? ''));
|
||||
showToast('复制成功');
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
'账单编号' + ': ${model.orderId}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xE5FFFFFF),
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
2.sizeBoxW,
|
||||
Image.asset(
|
||||
'icon_copy.png'.mineImgPath,
|
||||
width: 24,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
2.sizeBoxH,
|
||||
Text(
|
||||
"状态: ${getStatus(model.status ?? 0)}",
|
||||
style: TextStyle(
|
||||
color: Color(0xffF68804),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
2.sizeBoxH,
|
||||
Text(
|
||||
model.createdAt?.utcToYMD() ?? "",
|
||||
style: TextStyle(fontSize: 12, color: Color(0xff525252)),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
0.5.line,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
///支付状态
|
||||
String getStatus(int status) {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return "进行中";
|
||||
case 2:
|
||||
return "购买失败";
|
||||
case 3:
|
||||
return "购买成功";
|
||||
}
|
||||
return "未知";
|
||||
}
|
||||
|
||||
Color getStatusColor(int status) {
|
||||
var statusStr = Color(0xffffd382);
|
||||
switch (status) {
|
||||
case 2:
|
||||
statusStr = Color(0xffFF1060);
|
||||
break;
|
||||
case 3:
|
||||
statusStr = Color(0xff28C445);
|
||||
break;
|
||||
}
|
||||
|
||||
return statusStr;
|
||||
}
|
||||
}
|
||||
|
||||
class InComeRecordItem extends StatelessWidget {
|
||||
final IncomeModel model;
|
||||
const InComeRecordItem(this.model, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: Column(children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"${model.tranType}",
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFEFEFEF),
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14.0),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(vertical: 4),
|
||||
child: Text(
|
||||
model.desc ?? "",
|
||||
style: TextStyle(fontSize: 12, color: Colors.white60),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
DateTimeUtil.utc2iso(model.createdAt ?? ''),
|
||||
style: const TextStyle(
|
||||
color: Color(0xFF525252),
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 12.0),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
],
|
||||
),
|
||||
),
|
||||
12.sizeBoxW,
|
||||
Text(
|
||||
model.tranTypeInt == 111
|
||||
? "+${model.actualAmount}次"
|
||||
: "+${model.actualAmount}金币",
|
||||
style: const TextStyle(
|
||||
color: const Color(0xFFF68804),
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 12.0),
|
||||
textAlign: TextAlign.left)
|
||||
],
|
||||
),
|
||||
0.5.line,
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
//提现明细cell
|
||||
class WithdrawalRecordItem extends StatefulWidget {
|
||||
final ListBean model;
|
||||
const WithdrawalRecordItem(this.model, {super.key});
|
||||
|
||||
@override
|
||||
State<WithdrawalRecordItem> createState() => _WithdrawalRecordItemState();
|
||||
}
|
||||
|
||||
class _WithdrawalRecordItemState extends State<WithdrawalRecordItem> {
|
||||
ListBean get model => widget.model;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
12.sizeBoxH,
|
||||
Text(
|
||||
'${(model.money ?? 0) ~/ 100}元',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColors.actionRed,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
6.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'账单编号' + ': ${model.id}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xE5FFFFFF),
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () {
|
||||
///复制到剪切板
|
||||
Clipboard.setData(ClipboardData(text: model.id ?? ''));
|
||||
showToast('复制成功');
|
||||
},
|
||||
child: Image.asset(
|
||||
'mine_copy.png'.mineImgPath,
|
||||
width: 24,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
8.sizeBoxH,
|
||||
Text(
|
||||
'${getPayType(model.payType ?? "")}${getStatus(model.status ?? 0)}',
|
||||
style: TextStyle(fontSize: 12, color: getStatusColor()),
|
||||
),
|
||||
6.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
DateTimeUtil.utc2iso(model.createdAt ?? ''),
|
||||
style: TextStyle(fontSize: 12, color: Color(0x8CFFFFFF)),
|
||||
),
|
||||
Spacer(),
|
||||
if (model.status != 5 && model.status != 1) ...[
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => setState(() {
|
||||
model.showReason = !model.showReason;
|
||||
}),
|
||||
child: Text(
|
||||
'查看原因',
|
||||
style: TextStyle(fontSize: 12, color: AppColors.actionRed),
|
||||
),
|
||||
)
|
||||
],
|
||||
],
|
||||
),
|
||||
if (model.showReason) ...[
|
||||
12.sizeBoxH,
|
||||
Text(
|
||||
'${model.statusDesc}',
|
||||
style: TextStyle(fontSize: 12, color: Colors.white),
|
||||
),
|
||||
],
|
||||
12.sizeBoxH,
|
||||
0.5.line,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String getPayType(String payType) {
|
||||
if (payType.endsWith("alipay")) {
|
||||
return "支付宝";
|
||||
} else if (payType.endsWith("usdt")) {
|
||||
return "USDT";
|
||||
} else {
|
||||
return "银行卡";
|
||||
}
|
||||
}
|
||||
|
||||
///支付状态
|
||||
String getStatus(int status) {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return '提现审核中';
|
||||
case 2:
|
||||
return '审核通过,转账中';
|
||||
case 3:
|
||||
return '提现已拒绝';
|
||||
case 4:
|
||||
return '未知错误';
|
||||
case 5:
|
||||
return '提现成功';
|
||||
case 6:
|
||||
return '提现失败';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
///支付状态
|
||||
Color getStatusColor() {
|
||||
if (model.status == 5) {
|
||||
return Color(0xff0360FC);
|
||||
} else {
|
||||
return Color(0x8CFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
/// hasNext : true
|
||||
|
||||
class WithdrawDetailsModel {
|
||||
bool? hasNext;
|
||||
List<ListBean>? list;
|
||||
List<ResultBean>? result;
|
||||
int? total;
|
||||
|
||||
static WithdrawDetailsModel? fromJson(Map<String, dynamic> map) {
|
||||
WithdrawDetailsModel withdrawDetailsModel = WithdrawDetailsModel();
|
||||
withdrawDetailsModel.hasNext = map['hasNext'];
|
||||
withdrawDetailsModel.list = []..addAll((map['list'] as List? ?? []).map((o) => ListBean.fromMap(o)));
|
||||
withdrawDetailsModel.result = []..addAll((map['result'] as List? ?? []).map((o) => ResultBean.fromMap(o)));
|
||||
withdrawDetailsModel.total = map['total'];
|
||||
return withdrawDetailsModel;
|
||||
}
|
||||
|
||||
Map toJson() => {
|
||||
"hasNext": hasNext,
|
||||
"list": list,
|
||||
"result": result,
|
||||
"total": total,
|
||||
};
|
||||
}
|
||||
|
||||
class ResultBean {
|
||||
int? uid;
|
||||
int? amount;
|
||||
int? money;
|
||||
int? payMoney;
|
||||
int? withdrawType;
|
||||
int? status;
|
||||
String? id;
|
||||
String? name;
|
||||
String? oid;
|
||||
String? payType;
|
||||
String? actName;
|
||||
String? act;
|
||||
String? userIp;
|
||||
String? deviceType;
|
||||
String? devID;
|
||||
String? statusDesc;
|
||||
String? checkedAt;
|
||||
String? progressAt;
|
||||
String? failureAt;
|
||||
String? successAt;
|
||||
String? updatedAt;
|
||||
String? createdAt;
|
||||
String? receivedAt;
|
||||
|
||||
static ResultBean fromMap(Map<String, dynamic> map) {
|
||||
ResultBean info = ResultBean();
|
||||
info.id = map['id'];
|
||||
info.uid = map['uid'];
|
||||
info.name = map['name'];
|
||||
info.amount = map['amount'];
|
||||
info.oid = map['oid'];
|
||||
info.money = map['money'];
|
||||
info.payMoney = map['payMoney'];
|
||||
info.payType = map['payType'];
|
||||
info.withdrawType = map['withdrawType'];
|
||||
info.actName = map['actName'];
|
||||
info.act = map['act'];
|
||||
info.userIp = map['userIp'];
|
||||
info.deviceType = map['deviceType'];
|
||||
info.devID = map['devID'];
|
||||
info.status = map['status'];
|
||||
info.statusDesc = map['statusDesc'];
|
||||
info.checkedAt = map['checkedAt'];
|
||||
info.progressAt = map['progressAt'];
|
||||
info.failureAt = map['failureAt'];
|
||||
info.successAt = map['successAt'];
|
||||
info.updatedAt = map['updatedAt'];
|
||||
info.createdAt = map['createdAt'];
|
||||
info.receivedAt = map['receivedAt'];
|
||||
return info;
|
||||
}
|
||||
|
||||
Map toJson() => {
|
||||
"id": id,
|
||||
"uid": uid,
|
||||
"name": name,
|
||||
"amount": amount,
|
||||
"oid": oid,
|
||||
"money": money,
|
||||
"payMoney": payMoney,
|
||||
"payType": payType,
|
||||
"withdrawType": withdrawType,
|
||||
"actName": actName,
|
||||
"act": act,
|
||||
"userIp": userIp,
|
||||
"deviceType": deviceType,
|
||||
"devID": devID,
|
||||
"status": status,
|
||||
"statusDesc": statusDesc,
|
||||
"checkedAt": checkedAt,
|
||||
"progressAt": progressAt,
|
||||
"failureAt": failureAt,
|
||||
"successAt": successAt,
|
||||
"updatedAt": updatedAt,
|
||||
"createdAt": createdAt,
|
||||
"receivedAt": receivedAt,
|
||||
};
|
||||
}
|
||||
|
||||
class ListBean {
|
||||
int? money;
|
||||
int? payMoney;
|
||||
int? uid;
|
||||
int? amount;
|
||||
int? withdrawType;
|
||||
int? status;
|
||||
String? id;
|
||||
String? orderId;
|
||||
String? name;
|
||||
String? oid;
|
||||
String? payType;
|
||||
String? actName;
|
||||
String? act;
|
||||
String? userIp;
|
||||
String? deviceType;
|
||||
String? devID;
|
||||
String? statusDesc;
|
||||
String? checkedAt;
|
||||
String? progressAt;
|
||||
String? failureAt;
|
||||
String? successAt;
|
||||
String? updatedAt;
|
||||
String? createdAt;
|
||||
String? desc;
|
||||
String? receivedAt;
|
||||
String? productName;
|
||||
double? actualAmount;
|
||||
bool showReason = false; //本地添加字段,是否展示原因
|
||||
|
||||
static ListBean fromMap(Map<String, dynamic> map) {
|
||||
ListBean info = ListBean();
|
||||
info.id = map['id'];
|
||||
info.orderId = map['orderId'];
|
||||
info.uid = map['uid'];
|
||||
info.name = map['name'];
|
||||
info.amount = map['amount'];
|
||||
info.oid = map['oid'];
|
||||
info.money = map['money'];
|
||||
info.payMoney = map['payMoney'];
|
||||
info.payType = map['payType'];
|
||||
info.withdrawType = map['withdrawType'];
|
||||
info.actName = map['actName'];
|
||||
info.act = map['act'];
|
||||
info.userIp = map['userIp'];
|
||||
info.deviceType = map['deviceType'];
|
||||
info.devID = map['devID'];
|
||||
info.status = map['status'];
|
||||
info.statusDesc = map['statusDesc'];
|
||||
info.checkedAt = map['checkedAt'];
|
||||
info.progressAt = map['progressAt'];
|
||||
info.failureAt = map['failureAt'];
|
||||
info.successAt = map['successAt'];
|
||||
info.updatedAt = map['updatedAt'];
|
||||
info.createdAt = map['createdAt'];
|
||||
info.receivedAt = map['receivedAt'];
|
||||
info.desc = map['desc'];
|
||||
info.actualAmount = map['actualAmount']?.toDouble() ?? .0;
|
||||
info.productName = map['productName'];
|
||||
return info;
|
||||
}
|
||||
|
||||
Map toJson() => {
|
||||
"id": id,
|
||||
"uid": uid,
|
||||
"name": name,
|
||||
"amount": amount,
|
||||
"oid": oid,
|
||||
"money": money,
|
||||
"payMoney": payMoney,
|
||||
"payType": payType,
|
||||
"withdrawType": withdrawType,
|
||||
"actName": actName,
|
||||
"act": act,
|
||||
"userIp": userIp,
|
||||
"deviceType": deviceType,
|
||||
"devID": devID,
|
||||
"status": status,
|
||||
"statusDesc": statusDesc,
|
||||
"checkedAt": checkedAt,
|
||||
"progressAt": progressAt,
|
||||
"failureAt": failureAt,
|
||||
"successAt": successAt,
|
||||
"updatedAt": updatedAt,
|
||||
"createdAt": createdAt,
|
||||
"receivedAt": receivedAt,
|
||||
"desc": desc,
|
||||
"actualAmount": actualAmount,
|
||||
};
|
||||
}
|
||||
|
||||
class IncomeModel {
|
||||
String? id;
|
||||
int? uid;
|
||||
String? purchaseOrder;
|
||||
String? productID;
|
||||
num? amount;
|
||||
num? integral;
|
||||
String? realIntegral;
|
||||
num? actualIntegral;
|
||||
num? actualAmount;
|
||||
num? tax;
|
||||
num? taxAmount;
|
||||
String? channelType;
|
||||
String? tranType;
|
||||
num? tranTypeInt;
|
||||
num? performance;
|
||||
num? rechargeId;
|
||||
RechargeUser? rechargeUser;
|
||||
String? desc;
|
||||
String? createdAt;
|
||||
String? sysType;
|
||||
num? agentLevel;
|
||||
num? vipLevel;
|
||||
String? realAmount;
|
||||
String? money;
|
||||
String? wlRealAmount;
|
||||
num? fruitCoin;
|
||||
num? downloadCount;
|
||||
num? fruitCoinBalance;
|
||||
num? aiMateBalance;
|
||||
String? districtCode;
|
||||
String? promSeqe;
|
||||
bool? isDirect;
|
||||
String? discBindAt;
|
||||
|
||||
IncomeModel(
|
||||
{this.id,
|
||||
this.uid,
|
||||
this.purchaseOrder,
|
||||
this.productID,
|
||||
this.amount,
|
||||
this.integral,
|
||||
this.realIntegral,
|
||||
this.actualIntegral,
|
||||
this.actualAmount,
|
||||
this.tax,
|
||||
this.taxAmount,
|
||||
this.channelType,
|
||||
this.tranType,
|
||||
this.tranTypeInt,
|
||||
this.performance,
|
||||
this.rechargeId,
|
||||
this.rechargeUser,
|
||||
this.desc,
|
||||
this.createdAt,
|
||||
this.sysType,
|
||||
this.agentLevel,
|
||||
this.vipLevel,
|
||||
this.realAmount,
|
||||
this.money,
|
||||
this.wlRealAmount,
|
||||
this.fruitCoin,
|
||||
this.downloadCount,
|
||||
this.fruitCoinBalance,
|
||||
this.aiMateBalance,
|
||||
this.districtCode,
|
||||
this.promSeqe,
|
||||
this.isDirect,
|
||||
this.discBindAt});
|
||||
|
||||
handelMoney() {
|
||||
double price = (actualAmount ?? 0) / 10;
|
||||
return price.toStringAsFixed(2);
|
||||
}
|
||||
|
||||
IncomeModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
uid = json['uid'];
|
||||
purchaseOrder = json['purchaseOrder'];
|
||||
productID = json['productID'];
|
||||
amount = json['amount'];
|
||||
integral = json['integral'];
|
||||
realIntegral = json['realIntegral'];
|
||||
actualIntegral = json['actualIntegral'];
|
||||
actualAmount = json['actualAmount'];
|
||||
tax = json['tax'];
|
||||
taxAmount = json['taxAmount'];
|
||||
channelType = json['channelType'];
|
||||
tranType = json['tranType'];
|
||||
tranTypeInt = json['tranTypeInt'];
|
||||
performance = json['performance'];
|
||||
rechargeId = json['rechargeId'];
|
||||
rechargeUser = json['rechargeUser'] != null ? new RechargeUser.fromJson(json['rechargeUser']) : null;
|
||||
desc = json['desc'];
|
||||
createdAt = json['createdAt'];
|
||||
sysType = json['sysType'];
|
||||
agentLevel = json['agentLevel'];
|
||||
vipLevel = json['vipLevel'];
|
||||
realAmount = json['realAmount'];
|
||||
money = json['money'];
|
||||
wlRealAmount = json['wlRealAmount'];
|
||||
fruitCoin = json['fruitCoin'];
|
||||
downloadCount = json['downloadCount'];
|
||||
fruitCoinBalance = json['fruitCoinBalance'];
|
||||
aiMateBalance = json['aiMateBalance'];
|
||||
districtCode = json['districtCode'];
|
||||
promSeqe = json['promSeqe'];
|
||||
isDirect = json['isDirect'];
|
||||
discBindAt = json['DiscBindAt'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['id'] = this.id;
|
||||
data['uid'] = this.uid;
|
||||
data['purchaseOrder'] = this.purchaseOrder;
|
||||
data['productID'] = this.productID;
|
||||
data['amount'] = this.amount;
|
||||
data['integral'] = this.integral;
|
||||
data['realIntegral'] = this.realIntegral;
|
||||
data['actualIntegral'] = this.actualIntegral;
|
||||
data['actualAmount'] = this.actualAmount;
|
||||
data['tax'] = this.tax;
|
||||
data['taxAmount'] = this.taxAmount;
|
||||
data['channelType'] = this.channelType;
|
||||
data['tranType'] = this.tranType;
|
||||
data['tranTypeInt'] = this.tranTypeInt;
|
||||
data['performance'] = this.performance;
|
||||
data['rechargeId'] = this.rechargeId;
|
||||
if (this.rechargeUser != null) {
|
||||
data['rechargeUser'] = this.rechargeUser!.toJson();
|
||||
}
|
||||
data['desc'] = this.desc;
|
||||
data['createdAt'] = this.createdAt;
|
||||
data['sysType'] = this.sysType;
|
||||
data['agentLevel'] = this.agentLevel;
|
||||
data['vipLevel'] = this.vipLevel;
|
||||
data['realAmount'] = this.realAmount;
|
||||
data['money'] = this.money;
|
||||
data['wlRealAmount'] = this.wlRealAmount;
|
||||
data['fruitCoin'] = this.fruitCoin;
|
||||
data['downloadCount'] = this.downloadCount;
|
||||
data['fruitCoinBalance'] = this.fruitCoinBalance;
|
||||
data['aiMateBalance'] = this.aiMateBalance;
|
||||
data['districtCode'] = this.districtCode;
|
||||
data['promSeqe'] = this.promSeqe;
|
||||
data['isDirect'] = this.isDirect;
|
||||
data['DiscBindAt'] = this.discBindAt;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class RechargeUser {
|
||||
int? uid;
|
||||
String? name;
|
||||
String? portrait;
|
||||
|
||||
RechargeUser({this.uid, this.name, this.portrait});
|
||||
|
||||
RechargeUser.fromJson(Map<String, dynamic> json) {
|
||||
uid = json['uid'];
|
||||
name = json['name'];
|
||||
portrait = json['portrait'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['uid'] = this.uid;
|
||||
data['name'] = this.name;
|
||||
data['portrait'] = this.portrait;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/hj_model/user/wallet_model.dart';
|
||||
import 'package:hgdj/hj_utils/api_service/mine_service.dart';
|
||||
import 'package:hgdj/tools_base/global_store/store.dart';
|
||||
import 'package:hgdj/tools_base/loading/loading_helper.dart';
|
||||
|
||||
import '../../../alert/mine/vip_level_dialog.dart';
|
||||
import 'package:hgdj/tools_base/toast.dart';
|
||||
import '../../../track_event_manager/device_service.dart';
|
||||
import '../mine_profit/bank_card_home_page.dart';
|
||||
import '../mine_profit/model/alipay_bank_list_model.dart';
|
||||
import 'in_come_entity.dart';
|
||||
|
||||
class WithdrawalLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
WithdrawalLogic get to => Get.find<WithdrawalLogic>();
|
||||
|
||||
TextEditingController? moneyController;
|
||||
TextEditingController? accountController;
|
||||
FocusNode focusNode = FocusNode();
|
||||
bool isShowLoading = false;
|
||||
|
||||
WalletModel? userIncomeModel;
|
||||
WithdrawConfig? configData;
|
||||
TextEditingController? nameController;
|
||||
bool isLoading = true;
|
||||
|
||||
int withdrawType = 1; // 0支付宝 1银行卡
|
||||
Channel? selectChannel;
|
||||
|
||||
num handlingFee = 0; //手续费
|
||||
num actualAmount = 0; //实际到账金额
|
||||
AccountInfoModel? bankModel;
|
||||
int get minBankCardMoney {
|
||||
return (configData?.getBankCardChannel?.minMoney ?? 0) ~/ 100;
|
||||
}
|
||||
|
||||
int get minUsdtMoney {
|
||||
return (configData?.getUsdtChannel?.minMoney ?? 0) ~/ 100;
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
moneyController = TextEditingController();
|
||||
nameController = TextEditingController();
|
||||
accountController = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
loadData(showLoading: true);
|
||||
globalStore.refreshWallet();
|
||||
}
|
||||
|
||||
void changeWithdrawType(String payType) {
|
||||
// withdrawType = value;
|
||||
selectChannel = configData?.channels
|
||||
?.firstWhere((element) => element.payType == payType);
|
||||
withdrawType = configData?.channels
|
||||
?.indexWhere((e) => e.payType == selectChannel?.payType) ??
|
||||
0;
|
||||
update();
|
||||
}
|
||||
|
||||
///计算提现手续费、实际到账金额
|
||||
void calcWithdrawAmount(String withdrawAmount) {
|
||||
if (withdrawAmount.isEmpty) {
|
||||
handlingFee = 0;
|
||||
actualAmount = 0;
|
||||
} else {
|
||||
num withdrawAmoutNum = num.parse(withdrawAmount);
|
||||
int coinTax = configData?.coinTax ?? 0;
|
||||
if (coinTax == 0) {
|
||||
handlingFee = 0;
|
||||
actualAmount = withdrawAmoutNum;
|
||||
} else {
|
||||
double value = coinTax / 100.0;
|
||||
final res = (withdrawAmoutNum * double.parse(value.toStringAsFixed(2)))
|
||||
.toStringAsFixed(2);
|
||||
handlingFee = double.parse(res).floor();
|
||||
actualAmount = withdrawAmoutNum - handlingFee;
|
||||
}
|
||||
}
|
||||
update(['money']);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
nameController?.dispose();
|
||||
moneyController?.dispose();
|
||||
accountController?.dispose();
|
||||
focusNode.dispose();
|
||||
}
|
||||
|
||||
Future<void> loadData({
|
||||
bool isRefresh = true,
|
||||
bool showLoading = false,
|
||||
}) async {
|
||||
//获取支付宝或者银行卡的费率
|
||||
_withdrawConfigReq();
|
||||
}
|
||||
|
||||
///提现配置请求
|
||||
void _withdrawConfigReq() async {
|
||||
final configData = await MineService.withdrawConfig();
|
||||
this.configData = configData;
|
||||
isLoading = false;
|
||||
// 优先银行卡,其次 usdt
|
||||
selectChannel = configData?.channels
|
||||
?.firstWhereOrNull((element) => element.payType == 'bankcard') ??
|
||||
configData?.channels
|
||||
?.firstWhereOrNull((element) => element.payType == 'usdt');
|
||||
if (selectChannel == null) {
|
||||
showToast('暂无可用提现通道');
|
||||
this.configData = null;
|
||||
} else {
|
||||
// 必须同步 withdrawType,页面按 channels[withdrawType] 取值,否则会索引错位甚至越界
|
||||
withdrawType = configData?.channels
|
||||
?.indexWhere((e) => e.payType == selectChannel?.payType) ??
|
||||
0;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
///提交提现
|
||||
void submitWithdraw() async {
|
||||
try {
|
||||
if (!globalStore.isRechargeVIP) {
|
||||
showVipLevelDialog("您还不是VIP,无法使用提现功能");
|
||||
return;
|
||||
}
|
||||
|
||||
if ("bankcard" == selectChannel?.payType) {
|
||||
//检验银行卡信息
|
||||
_commonWithdrawReq(true);
|
||||
} else if ("alipay" == selectChannel?.payType ||
|
||||
"usdt" == selectChannel?.payType) {
|
||||
_commonWithdrawReq(false);
|
||||
}
|
||||
} catch (e) {
|
||||
showToast("提现错误:$e");
|
||||
}
|
||||
}
|
||||
|
||||
///公用提现方法
|
||||
void _commonWithdrawReq(bool isbankType) async {
|
||||
Channel channel = configData!.channels![withdrawType];
|
||||
String money = moneyController?.text.trim() ?? "";
|
||||
String accountDesc = accountController?.text.trim() ?? "";
|
||||
if (isbankType) {
|
||||
accountDesc = bankModel?.act ?? "";
|
||||
}
|
||||
if (money.isEmpty) {
|
||||
showToast("提现金额不能为空");
|
||||
return;
|
||||
}
|
||||
if (isbankType && bankModel == null) {
|
||||
showToast("请选择提现银行卡号");
|
||||
return;
|
||||
}
|
||||
if (!isbankType && accountDesc.isEmpty) {
|
||||
showToast("请输入钱包地址");
|
||||
return;
|
||||
}
|
||||
|
||||
double incomeMoneyYuan = (userIncomeModel?.balance ?? 0) / 10;
|
||||
int withdrawMoneyYuan = int.parse(money);
|
||||
if (withdrawMoneyYuan > incomeMoneyYuan) {
|
||||
showToast("提现金额不能大于余额");
|
||||
return;
|
||||
}
|
||||
|
||||
int minMoneyFen = configData?.channels![withdrawType].minMoney ?? 0;
|
||||
double minMoneyYuan = minMoneyFen / 100;
|
||||
if (withdrawMoneyYuan < minMoneyYuan) {
|
||||
showToast("单笔提现金额不小于$minMoneyYuan元");
|
||||
return;
|
||||
}
|
||||
int maxMoneyFen = configData?.channels![withdrawType].maxMoney ?? 0;
|
||||
double maxMoneyYuan = maxMoneyFen / 100;
|
||||
if (withdrawMoneyYuan > maxMoneyYuan) {
|
||||
showToast("单笔提现金额不大于$maxMoneyYuan元");
|
||||
return;
|
||||
}
|
||||
|
||||
LoadingHelper.showLoading();
|
||||
|
||||
String deviceId = DeviceInfoService.deviceId;
|
||||
String payType = channel.payType ?? "";
|
||||
//payType 提现方式,alipay,bankcard,usdt
|
||||
//money 提现金额
|
||||
//name 用户名
|
||||
//withdrawType 提现类型,0,代理提现; 1,金币提现
|
||||
//actName 交易账户持有人
|
||||
//act 交易账户
|
||||
//devID 设备id
|
||||
//productType 产品类型 0站群 1棋牌
|
||||
var result = await MineService.withdraw(
|
||||
payType,
|
||||
accountDesc,
|
||||
withdrawMoneyYuan * 100,
|
||||
globalStore.meInfo?.name ?? "",
|
||||
bankModel?.actName,
|
||||
deviceId,
|
||||
bankModel?.bankCode,
|
||||
1,
|
||||
0,
|
||||
);
|
||||
LoadingHelper.dismissLoading();
|
||||
if (result == true) {
|
||||
globalStore.refreshWallet(refresh: true);
|
||||
showToast("提现提交成功~");
|
||||
|
||||
clearInputData();
|
||||
} else {
|
||||
showToast("提现失败~");
|
||||
}
|
||||
}
|
||||
|
||||
void gotoBankList() async {
|
||||
var ret = await Get.to(
|
||||
BankCardHomePage(selectModel: bankModel),
|
||||
preventDuplicates: false,
|
||||
);
|
||||
if (ret is AccountInfoModel) {
|
||||
bankModel = ret;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
clearInputData() {
|
||||
nameController?.clear();
|
||||
accountController?.clear();
|
||||
moneyController?.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/assets_tool/images.dart';
|
||||
import 'package:hgdj/hj_page/mine/widgets/gradient_text.dart';
|
||||
import 'package:hgdj/hj_utils/screen.dart';
|
||||
import 'package:hgdj/tools_base/global_store/store.dart';
|
||||
import 'package:hgdj/tools_base/loading/loading_center_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../assets_tool/app_colors.dart';
|
||||
import '../../../hj_utils/widget_util.dart';
|
||||
import '../../../routers/jump_router.dart';
|
||||
import 'in_come_entity.dart';
|
||||
import 'mine_withdrawal_record_page.dart';
|
||||
import 'withdrawal_logic.dart';
|
||||
|
||||
//我要提现页面
|
||||
class WithdrawalPage extends StatelessWidget {
|
||||
const WithdrawalPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetBuilder<WithdrawalLogic>(
|
||||
init: WithdrawalLogic(),
|
||||
builder: (logic) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
'我要提现',
|
||||
style: TextStyle(
|
||||
color: Color(0xE5FFFFFF),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
GestureDetector(
|
||||
child: Text(
|
||||
'明细',
|
||||
style: TextStyle(color: Color(0x73FFFFFF), fontSize: 12),
|
||||
),
|
||||
onTap: () => Get.to(RecordsPage(RecordType.withdraw)),
|
||||
),
|
||||
16.w.sizeBoxW,
|
||||
],
|
||||
),
|
||||
body: () {
|
||||
if (logic.isLoading) return LoadingCenterWidget();
|
||||
if (logic.configData == null) return CErrorWidget();
|
||||
const measureStyle = TextStyle(fontSize: 14);
|
||||
var textPainter = TextPainter(
|
||||
text: TextSpan(
|
||||
text: '',
|
||||
style: measureStyle,
|
||||
),
|
||||
textDirection: TextDirection.ltr,
|
||||
textWidthBasis: TextWidthBasis.longestLine,
|
||||
)..layout();
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
keyboardDismissBehavior:
|
||||
ScrollViewKeyboardDismissBehavior.onDrag,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(left: 16.w, right: 16.w),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
margin:
|
||||
EdgeInsets.only(top: 12.w, bottom: 18.w),
|
||||
padding: EdgeInsets.symmetric(vertical: 12.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0x0DFFFFFF),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
height: 22,
|
||||
width: 8,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(11),
|
||||
bottomRight: Radius.circular(11),
|
||||
),
|
||||
color: AppColors.actionRed,
|
||||
),
|
||||
),
|
||||
12.sizeBoxW,
|
||||
Text(
|
||||
"余额(元)",
|
||||
style: const TextStyle(
|
||||
color: AppColors.actionRed,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
12.sizeBoxH,
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 20),
|
||||
child: Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'coin_icon.webp'.mineImgPath,
|
||||
width: 30),
|
||||
4.sizeBoxW,
|
||||
Consumer<GlobalStore>(
|
||||
builder: (_, store, __) {
|
||||
logic.userIncomeModel =
|
||||
store.wallet;
|
||||
return GradientText(
|
||||
((store.wallet?.balance ?? 0) *
|
||||
10 /
|
||||
100)
|
||||
.toStringAsFixed(2),
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Color(0xffFFE8BE),
|
||||
Color(0xffE6B764)
|
||||
],
|
||||
tileMode: TileMode.mirror,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 31.5,
|
||||
fontWeight: FontWeight
|
||||
.w500), //目前fontSize设置为31.5 设置为32,显示不完全,存在系统bug
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'提现币类:',
|
||||
style: textStyle(
|
||||
14, Color(0xE5FFFFFF), FontWeight.w500),
|
||||
),
|
||||
15.sizeBoxW,
|
||||
Text(
|
||||
'人民币',
|
||||
style: textStyle(
|
||||
14, Color(0x8CFFFFFF), FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
16.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"提现金额:",
|
||||
style: textStyle(
|
||||
14, Color(0xE5FFFFFF), FontWeight.w500),
|
||||
),
|
||||
10.sizeBoxW,
|
||||
Expanded(
|
||||
child: Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
height: 40,
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Colors.white.withValues(alpha: .05),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: TextField(
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp("[0-9]")),
|
||||
LengthLimitingTextInputFormatter(9),
|
||||
],
|
||||
controller: logic.moneyController,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400),
|
||||
cursorColor:
|
||||
Colors.white.withValues(alpha: 0.7),
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(bottom: 8),
|
||||
hintStyle: TextStyle(
|
||||
color: Color(0xFF525252),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400),
|
||||
hintText:
|
||||
'单笔提现金额范围 ${_getPayMoneyRange(logic)}元', //"您目前
|
||||
),
|
||||
focusNode: logic.focusNode,
|
||||
onChanged: (value) =>
|
||||
logic.calcWithdrawAmount(value)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
16.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"提现方式:",
|
||||
style: textStyle(
|
||||
14, Color(0xE5FFFFFF), FontWeight.w500),
|
||||
),
|
||||
16.sizeBoxW,
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: SizedBox(
|
||||
height: 30,
|
||||
child: Row(
|
||||
children: logic.configData?.realChannel
|
||||
.asMap()
|
||||
.map((index, e) => MapEntry(
|
||||
index,
|
||||
_buildPayTypeUI(
|
||||
e, logic, index)))
|
||||
.values
|
||||
.toList() ??
|
||||
[],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
16.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
if (_isUsdt(logic)) ...[
|
||||
Text(
|
||||
'USDT地址:',
|
||||
style: textStyle(
|
||||
14, Color(0xE5FFFFFF), FontWeight.w500),
|
||||
),
|
||||
10.sizeBoxW,
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Colors.white.withValues(alpha: .05),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: TextField(
|
||||
textAlignVertical:
|
||||
TextAlignVertical.center,
|
||||
controller: logic.accountController,
|
||||
maxLines: 1,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: _getHintText(logic),
|
||||
hintStyle: TextStyle(
|
||||
color: Color(0xff999999),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400),
|
||||
isCollapsed: true,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical:
|
||||
(32 - textPainter.height) / 2,
|
||||
),
|
||||
),
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
] else ...[
|
||||
Text(
|
||||
'银行卡号:',
|
||||
style: textStyle(
|
||||
14, Color(0xE5FFFFFF), FontWeight.w500),
|
||||
),
|
||||
10.sizeBoxW,
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => logic.gotoBankList(),
|
||||
child: Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
height: 37,
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Colors.white.withValues(alpha: .05),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
logic.bankModel == null
|
||||
? "请选择提现银行账号"
|
||||
: "${logic.bankModel?.getBankName()}(${logic.bankModel?.act?.substring((logic.bankModel?.act?.length ?? 4) - 4)}) ${logic.bankModel?.actName}",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: logic.bankModel == null
|
||||
? Color(0xff525252)
|
||||
: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
6.sizeBoxW,
|
||||
Icon(Icons.keyboard_arrow_right,
|
||||
color: Colors.white, size: 16),
|
||||
10.sizeBoxW,
|
||||
],
|
||||
),
|
||||
),
|
||||
)),
|
||||
]
|
||||
],
|
||||
),
|
||||
16.sizeBoxH,
|
||||
GetBuilder<WithdrawalLogic>(
|
||||
init: logic,
|
||||
id: 'money',
|
||||
builder: (controller) => EasyRichText(
|
||||
'手续费率: ${logic.configData?.coinTax ?? 0}% 实际到账金额: ${logic.actualAmount}',
|
||||
defaultStyle: textStyle(
|
||||
14, Color(0xE5FFFFFF), FontWeight.w500),
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString:
|
||||
'${logic.configData?.coinTax ?? 0}%',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0x8CFFFFFF),
|
||||
),
|
||||
),
|
||||
EasyRichTextPattern(
|
||||
targetString:
|
||||
'实际到账金额: ${logic.handlingFee}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0x8CFFFFFF),
|
||||
),
|
||||
),
|
||||
EasyRichTextPattern(
|
||||
targetString: '${logic.actualAmount}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0x8CFFFFFF),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
18.sizeBoxH,
|
||||
Text(
|
||||
"提现规则:",
|
||||
style: const TextStyle(
|
||||
color: Color(0xE5FFFFFF),
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16.0),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
Text(
|
||||
"1、每次提现金额最低${(logic.configData?.channels == null ? 0 : logic.selectChannel?.minMoney ?? 0) ~/ 100}元起,"
|
||||
"单笔提现最大${(logic.configData?.channels == null ? 0 : logic.selectChannel?.maxMoney ?? 0) ~/ 100}元,且为整数。\n"
|
||||
"2、每次提现收取${logic.configData?.coinTax}%手续费。\n"
|
||||
"3、仅支持银行卡提现,收款账户卡号与姓名一致,到账时间未72小时内。\n"
|
||||
"4、申请提现后请随时关注收款账户进款通知,长时间未到账,请及时联系客服。\n",
|
||||
style: const TextStyle(
|
||||
color: Color(0x8CFFFFFF),
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 12.0,
|
||||
height: 2),
|
||||
),
|
||||
30.sizeBoxH,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => logic.submitWithdraw(),
|
||||
child: Container(
|
||||
height: 47,
|
||||
alignment: Alignment.center,
|
||||
margin: EdgeInsets.symmetric(horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.actionRed,
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
),
|
||||
child: Text(
|
||||
'立即提现',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
)),
|
||||
),
|
||||
10.sizeBoxH,
|
||||
EasyRichText(
|
||||
'提现中如有问题,请联系 在线客服',
|
||||
defaultStyle:
|
||||
textStyle(12, Colors.white, FontWeight.w400),
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString: '在线客服',
|
||||
style: TextStyle(color: Color(0xffFFD460)),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = pushToCustomService,
|
||||
),
|
||||
],
|
||||
),
|
||||
34.sizeBoxH,
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}());
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
///支付类型
|
||||
Widget _buildPayTypeUI(Channel channel, WithdrawalLogic logic, int index) {
|
||||
bool isSelected = logic.selectChannel?.payType == channel.payType;
|
||||
return InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => logic.changeWithdrawType(channel.payType ?? ''),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
channel.payType == 'usdt'
|
||||
? 'ic_usdt.png'.mineImgPath
|
||||
: 'ic_union.png'.mineImgPath,
|
||||
width: 30),
|
||||
4.sizeBoxW,
|
||||
Text(_getPayTypeName(channel.payType ?? ""),
|
||||
style: TextStyle(color: Colors.white, fontSize: 14)),
|
||||
10.sizeBoxW,
|
||||
Image.asset(
|
||||
isSelected
|
||||
? 'radio_sel.png'.commonImgPath
|
||||
: 'mine_withdraw_nor.png'.mineImgPath,
|
||||
width: 24,
|
||||
),
|
||||
24.sizeBoxW,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
///获取支付方式名称
|
||||
String _getPayTypeName(String payType) {
|
||||
if ("alipay" == payType) {
|
||||
return "支付宝";
|
||||
} else if ("bankcard" == payType) {
|
||||
return "银行卡";
|
||||
} else if ("usdt" == payType) {
|
||||
return "USDT";
|
||||
}
|
||||
return "银行卡";
|
||||
}
|
||||
|
||||
///获取提现金额范围
|
||||
String _getPayMoneyRange(WithdrawalLogic logic) {
|
||||
final channel = _currentChannel(logic);
|
||||
if (channel == null) return "0";
|
||||
return "${(channel.minMoney ?? 0) / 100}-${(channel.maxMoney ?? 0) / 100}";
|
||||
}
|
||||
|
||||
String _getHintText(WithdrawalLogic logic) {
|
||||
final channel = _currentChannel(logic);
|
||||
switch (channel?.payType ?? "") {
|
||||
case 'alipay':
|
||||
return '请输入支付宝账号';
|
||||
case 'bankcard':
|
||||
return '请输入银行卡号';
|
||||
case 'usdt':
|
||||
return '请输入USDT地址';
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool _isUsdt(WithdrawalLogic logic) =>
|
||||
(_currentChannel(logic)?.payType ?? "") == 'usdt';
|
||||
|
||||
// 按 withdrawType 取当前通道,带越界保护(配置异常时不崩溃)
|
||||
Channel? _currentChannel(WithdrawalLogic logic) {
|
||||
final channels = logic.configData?.channels ?? [];
|
||||
final index = logic.withdrawType;
|
||||
if (index < 0 || index >= channels.length) return null;
|
||||
return channels[index];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user