fix: 完善资金充值/提现逻辑
- 添加交易账户余额检查 - 添加用户端订单管理页面 - 更新测试报告
This commit is contained in:
199
flutter_monisuo/lib/ui/pages/orders/fund_order_card.dart
Normal file
199
flutter_monisuo/lib/ui/pages/orders/fund_order_card.dart
Normal file
@@ -0,0 +1,199 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../data/models/order_models.dart';
|
||||
|
||||
class _FundOrderCard extends StatelessWidget {
|
||||
final OrderFund order;
|
||||
|
||||
const _FundOrderCard({required this.order});
|
||||
|
||||
Color _getStatusColor(int status, bool isDeposit) {
|
||||
if (isDeposit) {
|
||||
// 充值状态: 1=待付款, 2=待确认, 3=已完成, 4=已驳回, 5=已取消
|
||||
switch (status) {
|
||||
case 1:
|
||||
return AppColorScheme.warning;
|
||||
case 2:
|
||||
return AppColorScheme.info;
|
||||
case 3:
|
||||
return AppColorScheme.success;
|
||||
case 4:
|
||||
return AppColorScheme.error;
|
||||
case 5:
|
||||
return AppColorScheme.muted;
|
||||
default:
|
||||
return AppColorScheme.muted;
|
||||
}
|
||||
} else {
|
||||
// 提现状态: 1=待审批, 2=已完成, 3=已驳回, 4=已取消
|
||||
switch (status) {
|
||||
case 1:
|
||||
return AppColorScheme.warning;
|
||||
case 2:
|
||||
return AppColorScheme.success;
|
||||
case 3:
|
||||
return AppColorScheme.error;
|
||||
case 4:
|
||||
return AppColorScheme.muted;
|
||||
default:
|
||||
return AppColorScheme.muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String _getStatusText(int status, bool isDeposit) {
|
||||
if (isDeposit) {
|
||||
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 '未知';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = ShadTheme.of(context);
|
||||
final isDeposit = order.type == 1;
|
||||
final statusColor = _getStatusColor(order.status, isDeposit);
|
||||
|
||||
return ShadCard(
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${isDeposit ? '+' : '-'}${order.amount} USDT',
|
||||
style: theme.textTheme.large.copyWith(
|
||||
color: statusColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: statusColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
_getStatusText(order.status, isDeposit),
|
||||
style: theme.textTheme.small.copyWith(color: statusColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Row(
|
||||
children: [
|
||||
Text('订单号: ', style: theme.textTheme.muted),
|
||||
Text(order.orderNo, style: theme.textTheme.small),
|
||||
],
|
||||
),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Row(
|
||||
children: [
|
||||
Text('创建时间: ', style: theme.textTheme.muted),
|
||||
Text(
|
||||
order.createTime ?? '无',
|
||||
style: theme.textTheme.small,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (order.rejectReason != null && order.rejectReason!.isNotEmpty) ...[
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Row(
|
||||
children: [
|
||||
Text('驳回原因: ', style: theme.textTheme.muted),
|
||||
Expanded(
|
||||
child: Text(
|
||||
order.rejectReason!,
|
||||
style: theme.textTheme.small.copyWith(color: AppColorScheme.error),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
if (order.status == 1 && isDeposit) ...[
|
||||
SizedBox(height: AppSpacing.md),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ShadButton.outline(
|
||||
onPressed: () => _handleConfirmPay(context),
|
||||
child: const Text('已打款'),
|
||||
),
|
||||
),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
Expanded(
|
||||
child: ShadButton.outline(
|
||||
onPressed: () => _handleCancel(context),
|
||||
child: const Text('取消订单'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _handleConfirmPay(BuildContext context) async {
|
||||
final response = await context.read<AssetProvider>().confirmPay(order.orderNo);
|
||||
if (context.mounted) {
|
||||
if (response.success) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: const Text('已确认打款,请等待审核')),
|
||||
);
|
||||
context.read<AssetProvider>().refreshFundOrders();
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(response.message ?? '确认失败')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleCancel(BuildContext context) async {
|
||||
final response = await context.read<AssetProvider>().cancelOrder(order.orderNo);
|
||||
if (context.mounted) {
|
||||
if (response.success) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: const Text('订单已取消')),
|
||||
);
|
||||
context.read<AssetProvider>().refreshFundOrders();
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(response.message ?? '取消失败')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
flutter_monisuo/lib/ui/pages/orders/fund_orders_list.dart
Normal file
42
flutter_monisuo/lib/ui/pages/orders/fund_orders_list.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/constants/app_colors.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../providers/asset_provider.dart';
|
||||
import '../../../data/models/order_models.dart';
|
||||
|
||||
class _FundOrdersList extends StatelessWidget {
|
||||
final AssetProvider provider;
|
||||
|
||||
const _FundOrdersList({required this.provider});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = ShadTheme.of(context);
|
||||
final orders = provider.fundOrders;
|
||||
|
||||
if (orders.isEmpty) {
|
||||
return const _EmptyState(
|
||||
icon: LucideIcons.receipt,
|
||||
message: '暂无充提记录',
|
||||
);
|
||||
}
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => provider.refreshFundOrders(),
|
||||
color: theme.colorScheme.primary,
|
||||
child: ListView.separated(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: AppSpacing.pagePadding,
|
||||
itemCount: orders.length,
|
||||
separatorBuilder: (_, __) => Divider(color: theme.colorScheme.border, height: 1),
|
||||
itemBuilder: (context, index) {
|
||||
final order = orders[index];
|
||||
return _FundOrderCard(order: order);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
69
flutter_monisuo/lib/ui/pages/orders/orders_page.dart
Normal file
69
flutter_monisuo/lib/ui/pages/orders/orders_page.dart
Normal file
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/constants/app_colors.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../providers/asset_provider.dart';
|
||||
import '../home/home_page.dart';
|
||||
|
||||
/// 订单管理页面
|
||||
class OrdersPage extends StatefulWidget {
|
||||
const OrdersPage({super.key});
|
||||
|
||||
@override
|
||||
State<OrdersPage> createState() => _OrdersPageState();
|
||||
}
|
||||
|
||||
class _OrdersPageState extends State<OrdersPage> with AutomaticKeepAliveClientMixin {
|
||||
int _activeTab = 0;
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _loadData());
|
||||
}
|
||||
|
||||
void _loadData() {
|
||||
context.read<AssetProvider>().refreshAll();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.colorScheme.background,
|
||||
body: Consumer<AssetProvider>(
|
||||
builder: (context, provider) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => provider.refreshAll(force: true),
|
||||
color: theme.colorScheme.primary,
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: AppSpacing.pagePadding,
|
||||
child: Column(
|
||||
children: [
|
||||
_TabSelector(
|
||||
tabs: const ['充提记录', '交易记录'],
|
||||
selectedIndex: _activeTab,
|
||||
onChanged: (index) => setState(() => _activeTab = index),
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_activeTab == 0
|
||||
? _FundOrdersList(provider: provider)
|
||||
: _TradeOrdersList(provider: provider),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user