From a6f90530145e4575268c6571aece70e68cfd4931 Mon Sep 17 00:00:00 2001 From: sion Date: Mon, 6 Apr 2026 12:15:33 +0800 Subject: [PATCH] 111 --- .../lib/data/models/order_models.dart | 2 +- .../lib/ui/pages/home/home_page.dart | 501 ++++-------------- .../lib/ui/pages/orders/fund_order_card.dart | 59 ++- .../lib/ui/pages/orders/fund_orders_list.dart | 46 +- .../lib/ui/pages/orders/fund_orders_page.dart | 12 +- .../src/pages/monisuo/finance-orders.vue | 5 + monisuo-admin/src/pages/monisuo/orders.vue | 6 +- sql/init.sql | 6 + .../it/rattan/monisuo/entity/OrderFund.java | 2 +- .../rattan/monisuo/service/AssetService.java | 7 +- 10 files changed, 218 insertions(+), 428 deletions(-) diff --git a/flutter_monisuo/lib/data/models/order_models.dart b/flutter_monisuo/lib/data/models/order_models.dart index b31f73a..ef06289 100644 --- a/flutter_monisuo/lib/data/models/order_models.dart +++ b/flutter_monisuo/lib/data/models/order_models.dart @@ -79,7 +79,7 @@ class OrderFund { final String? receivableAmount; // 应收款项 final int status; // 充值状态: 1=待付款, 2=待确认, 3=已完成, 4=已驳回, 5=已取消 - // 提现状态: 1=待审批, 2=已完成, 3=已驳回, 4=已取消, 5=待财务审核 + // 提现状态: 1=待审批, 2=已出款, 3=已驳回, 4=已取消, 5=待财务审核 final int? walletId; // 冷钱包ID(充值) final String? walletAddress; // 钱包地址(充值/提现) final String? network; // 提现网络类型 diff --git a/flutter_monisuo/lib/ui/pages/home/home_page.dart b/flutter_monisuo/lib/ui/pages/home/home_page.dart index fe9db1c..cb4d449 100644 --- a/flutter_monisuo/lib/ui/pages/home/home_page.dart +++ b/flutter_monisuo/lib/ui/pages/home/home_page.dart @@ -1,25 +1,24 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:provider/provider.dart'; +import 'package:shadcn_ui/shadcn_ui.dart'; import '../../../core/theme/app_theme.dart'; -import '../../../core/theme/app_color_scheme.dart'; import '../../../core/theme/app_spacing.dart'; import '../../../core/theme/app_theme_extension.dart'; -import '../../../core/utils/toast_utils.dart'; import '../../../core/event/app_event_bus.dart'; import '../../../data/models/account_models.dart'; import '../../../data/services/bonus_service.dart'; +import '../../../data/services/asset_service.dart'; import '../../../providers/asset_provider.dart'; import '../../components/glass_panel.dart'; -import '../../components/neon_glow.dart'; -import '../main/main_page.dart'; import '../mine/welfare_center_page.dart'; +import '../asset/transfer_page.dart'; +import '../asset/components/asset_dialogs.dart'; import 'header_bar.dart'; import 'quick_actions_row.dart'; import 'hot_coins_section.dart'; import 'profit_analysis_page.dart'; +import 'bills_page.dart'; /// 首页 class HomePage extends StatefulWidget { @@ -106,7 +105,7 @@ class _HomePageState extends State // Header HeaderBar(), SizedBox(height: AppSpacing.md), - // 资产卡片(含总盈利 + 可折叠盈亏日历) + // 资产卡片(含预估盈亏) _AssetCard( overview: provider.overview, onDeposit: _showDeposit, @@ -115,9 +114,10 @@ class _HomePageState extends State // 快捷操作栏 QuickActionsRow( onDeposit: _showDeposit, - onWithdraw: () => _navigateToAssetPage(), - onTransfer: () => _navigateToAssetPage(), - onBills: () => _navigateToAssetPage(), + onWithdraw: _showWithdraw, + onTransfer: _navigateToTransfer, + onProfit: _navigateToProfitAnalysis, + onBills: _navigateToBills, ), SizedBox(height: AppSpacing.md), // 福利中心入口卡片 @@ -144,290 +144,92 @@ class _HomePageState extends State } void _showDeposit() { - final amountController = TextEditingController(); - final formKey = GlobalKey(); - - showShadDialog( - context: context, - builder: (ctx) => Dialog( - backgroundColor: Colors.transparent, - child: GlassPanel( - borderRadius: BorderRadius.circular(AppRadius.xxl), - padding: EdgeInsets.all(AppSpacing.lg), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - '充值', - style: AppTextStyles.headlineLarge(context).copyWith( - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: AppSpacing.xs), - Text( - '资产: USDT', - style: AppTextStyles.bodyMedium(context), - ), - ], - ), - Container( - padding: EdgeInsets.all(AppSpacing.sm), - decoration: BoxDecoration( - color: context.colors.surfaceContainerHigh, - borderRadius: BorderRadius.circular(AppRadius.md), - ), - child: Icon(LucideIcons.wallet, color: context.colors.secondary), - ), - ], - ), - SizedBox(height: AppSpacing.lg), - ShadForm( - key: formKey, - child: ShadInputFormField( - id: 'amount', - controller: amountController, - label: const Text('充值金额'), - placeholder: const Text('0.00'), - keyboardType: const TextInputType.numberWithOptions(decimal: true), - validator: (v) { - if (v == null || v.isEmpty) return '请输入金额'; - final n = double.tryParse(v); - if (n == null || n <= 0) return '请输入有效金额'; - return null; - }, - ), - ), - SizedBox(height: AppSpacing.lg), - Row( - children: [ - Expanded( - child: NeonButton( - text: '取消', - type: NeonButtonType.outline, - onPressed: () => Navigator.of(ctx).pop(), - height: 48, - showGlow: false, - ), - ), - SizedBox(width: AppSpacing.sm), - Expanded( - child: NeonButton( - text: '下一步', - type: NeonButtonType.primary, - onPressed: () async { - if (formKey.currentState!.saveAndValidate()) { - Navigator.of(ctx).pop(); - final response = await context - .read() - .deposit(amount: amountController.text); - if (mounted) { - if (response.success && response.data != null) { - _showDepositResultDialog(context, response.data!); - } else { - _showResultDialog( - '申请失败', - response.message ?? '请稍后重试', - ); - } - } - } - }, - height: 48, - showGlow: true, - ), - ), - ], - ), - ], - ), - ), - ), - ); + showDepositDialog(context); } - void _showDepositResultDialog(BuildContext context, Map data) { - final orderNo = data['orderNo'] as String? ?? ''; - final amount = data['amount']?.toString() ?? '0.00'; - final walletAddress = data['walletAddress'] as String? ?? ''; - final walletNetwork = data['walletNetwork'] as String? ?? 'TRC20'; - - showShadDialog( - context: context, - builder: (ctx) => Dialog( - backgroundColor: Colors.transparent, - child: GlassPanel( - borderRadius: BorderRadius.circular(AppRadius.xxl), - padding: EdgeInsets.all(AppSpacing.lg), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - NeonIcon( - icon: Icons.check_circle, - color: AppColorScheme.up, - size: 24, - ), - SizedBox(width: AppSpacing.sm), - Text( - '充值申请成功', - style: AppTextStyles.headlineLarge(context).copyWith( - fontWeight: FontWeight.bold, - ), - ), - ], - ), - SizedBox(height: AppSpacing.lg), - _InfoRow(label: '订单号', value: orderNo), - SizedBox(height: AppSpacing.sm), - _InfoRow(label: '充值金额', value: '$amount USDT', isBold: true), - SizedBox(height: AppSpacing.lg), - Text( - '请向以下地址转账:', - style: AppTextStyles.bodyMedium(context), - ), - SizedBox(height: AppSpacing.sm), - _WalletAddressCard(address: walletAddress, network: walletNetwork), - SizedBox(height: AppSpacing.md), - Container( - padding: EdgeInsets.all(AppSpacing.sm), - decoration: BoxDecoration( - color: AppColorScheme.warning.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(AppRadius.md), - border: Border.all(color: AppColorScheme.warning.withValues(alpha: 0.2)), - ), - child: Row( - children: [ - Icon(Icons.info_outline, size: 16, color: AppColorScheme.warning), - SizedBox(width: AppSpacing.sm), - Expanded( - child: Text( - '转账完成后请点击"已打款"按钮确认', - style: AppTextStyles.bodyMedium(context).copyWith( - color: AppColorScheme.warning, - ), - ), - ), - ], - ), - ), - SizedBox(height: AppSpacing.lg), - Row( - children: [ - Expanded( - child: NeonButton( - text: '稍后确认', - type: NeonButtonType.outline, - onPressed: () { - Navigator.of(ctx).pop(); - _navigateToAssetPage(); - }, - height: 44, - showGlow: false, - ), - ), - SizedBox(width: AppSpacing.sm), - Expanded( - child: NeonButton( - text: '已打款', - type: NeonButtonType.primary, - onPressed: () async { - Navigator.of(ctx).pop(); - final response = await context - .read() - .confirmPay(orderNo); - if (context.mounted) { - _showResultDialog( - response.success ? '确认成功' : '确认失败', - response.success ? '请等待管理员审核' : response.message, - ); - _navigateToAssetPage(); - } - }, - height: 44, - showGlow: true, - ), - ), - ], - ), - ], - ), - ), - ), - ); + void _showWithdraw() { + final balance = context.read().fundAccount?.balance ?? '0.00'; + showWithdrawDialog(context, balance); } - void _showResultDialog(String title, String? message) { - showShadDialog( - context: context, - builder: (ctx) => Dialog( - backgroundColor: Colors.transparent, - child: GlassPanel( - borderRadius: BorderRadius.circular(AppRadius.xxl), - padding: EdgeInsets.all(AppSpacing.lg), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text(title, - style: AppTextStyles.headlineLarge(context).copyWith( - fontWeight: FontWeight.bold, - )), - if (message != null) ...[ - SizedBox(height: AppSpacing.sm), - Text(message, - style: AppTextStyles.bodyMedium(context), - textAlign: TextAlign.center), - ], - SizedBox(height: AppSpacing.lg), - SizedBox( - width: double.infinity, - child: NeonButton( - text: '确定', - type: NeonButtonType.primary, - onPressed: () => Navigator.of(ctx).pop(), - height: 44, - showGlow: false, - ), - ), - ], - ), - ), - ), - ); - } - - /// 跳转到资产页面 - void _navigateToAssetPage() { - final mainState = context.findAncestorStateOfType(); - mainState?.switchToTab(3); - } - - void _navigateToWelfareCenter() { + void _navigateToTransfer() { Navigator.push( context, - MaterialPageRoute(builder: (_) => const WelfareCenterPage()), + MaterialPageRoute(builder: (_) => const TransferPage()), + ); + } + + void _navigateToProfitAnalysis() { + Navigator.push( + context, + MaterialPageRoute(builder: (_) => const ProfitAnalysisPage()), + ); + } + + void _navigateToBills() { + Navigator.push( + context, + MaterialPageRoute(builder: (_) => const BillsPage()), ); } } -/// Header 栏:品牌名 + 搜索/通知/头像 -/// 资产卡片(含总盈利) -class _AssetCard extends StatelessWidget { +/// 资产卡片(含预估盈亏) +class _AssetCard extends StatefulWidget { final AssetOverview? overview; final VoidCallback onDeposit; const _AssetCard({required this.overview, required this.onDeposit}); + @override + State<_AssetCard> createState() => _AssetCardState(); +} + +class _AssetCardState extends State<_AssetCard> { + Map? _profitData; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) => _loadProfit()); + } + + @override + void didUpdateWidget(covariant _AssetCard oldWidget) { + super.didUpdateWidget(oldWidget); + // overview 更新时重新加载盈亏数据 + if (widget.overview != oldWidget.overview) { + _loadProfit(); + } + } + + Future _loadProfit() async { + try { + final now = DateTime.now(); + final response = await context.read().getDailyProfit( + year: now.year, + month: now.month, + ); + if (mounted && response.success && response.data != null) { + setState(() { + _profitData = response.data; + }); + } + } catch (_) {} + } + + double get _todayProfit { + if (_profitData == null) return 0; + final daily = _profitData!['daily'] as Map?; + if (daily == null) return 0; + final todayKey = DateTime.now().toIso8601String().substring(0, 10); + final todayValue = daily[todayKey]; + if (todayValue == null) return 0; + return (todayValue as num).toDouble(); + } + double get _totalProfit { - final v = overview?.totalProfit; + final v = widget.overview?.totalProfit; if (v == null) return 0; return double.tryParse(v) ?? 0; } @@ -436,15 +238,14 @@ class _AssetCard extends StatelessWidget { Widget build(BuildContext context) { final upColor = context.appColors.up; final downColor = context.appColors.down; - final isProfit = _totalProfit >= 0; // 总资产 - final totalAsset = overview?.totalAsset ?? '0.00'; + final totalAsset = widget.overview?.totalAsset ?? '0.00'; final displayAsset = _formatAsset(totalAsset); return GlassPanel( padding: EdgeInsets.all(20), - borderRadius: BorderRadius.circular(AppRadius.lg), // 14px + borderRadius: BorderRadius.circular(AppRadius.lg), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -454,15 +255,12 @@ class _AssetCard extends StatelessWidget { children: [ Text( '预估总资产(USDT)', - style: AppTextStyles.bodyLarge(context), // 13px + style: AppTextStyles.bodyLarge(context), ), GestureDetector( - onTap: onDeposit, + onTap: widget.onDeposit, child: Container( - padding: EdgeInsets.symmetric( - horizontal: 10, - vertical: 5, - ), + padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration( color: context.colors.primary, borderRadius: BorderRadius.circular(AppRadius.sm), @@ -496,14 +294,14 @@ class _AssetCard extends StatelessWidget { ), SizedBox(height: AppSpacing.md), - // 盈亏统计区:今日盈亏 | 总盈亏 + // 盈亏统计区:预估今日盈亏 | 预估总盈亏 Row( children: [ - // 今日盈亏卡片 + // 预估今日盈亏 Expanded( child: _ProfitStatCard( - label: '今日盈亏', - value: null, // 移除日历后不显示今日盈亏 + label: '预估今日盈亏', + value: _todayProfit, upColor: upColor, downColor: downColor, onTap: () => Navigator.push( @@ -513,10 +311,10 @@ class _AssetCard extends StatelessWidget { ), ), SizedBox(width: AppSpacing.sm), - // 总盈亏卡片 + // 预估总盈亏 Expanded( child: _ProfitStatCard( - label: '总盈亏', + label: '预估总盈亏', value: _totalProfit, upColor: upColor, downColor: downColor, @@ -554,7 +352,7 @@ class _WelfareCard extends StatelessWidget { width: double.infinity, padding: EdgeInsets.all(AppSpacing.lg), decoration: BoxDecoration( - color: context.colors.surface, // 白色背景(跟随主题) + color: context.colors.surface, borderRadius: BorderRadius.circular(AppRadius.xl), border: Border.all(color: context.colors.outlineVariant.withValues(alpha: 0.2)), ), @@ -596,14 +394,14 @@ class _WelfareCard extends StatelessWidget { ], ), ), - // 右侧按钮 - 黄色背景 + // 右侧按钮 Container( padding: EdgeInsets.symmetric( horizontal: AppSpacing.md, vertical: AppSpacing.sm, ), decoration: BoxDecoration( - color: const Color(0xFFF59E0B), // 黄色背景 + color: const Color(0xFFF59E0B), borderRadius: BorderRadius.circular(AppRadius.full), ), child: Row( @@ -630,7 +428,7 @@ class _WelfareCard extends StatelessWidget { '查看', style: AppTextStyles.headlineSmall(context).copyWith( fontWeight: FontWeight.w700, - color: Colors.white, // 白色文字 + color: Colors.white, ), ), ], @@ -818,92 +616,10 @@ class _HoldingItem extends StatelessWidget { } } -/// 信息行组件 -class _InfoRow extends StatelessWidget { - final String label; - final String value; - final bool isBold; - - const _InfoRow({required this.label, required this.value, this.isBold = false}); - - @override - Widget build(BuildContext context) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(label, - style: AppTextStyles.bodyMedium(context)), - Text(value, - style: AppTextStyles.bodyMedium(context).copyWith( - fontWeight: isBold ? FontWeight.bold : FontWeight.normal, - fontFeatures: isBold ? const [FontFeature.tabularFigures()] : null, - )), - ], - ); - } -} - -/// 钱包地址卡片 -class _WalletAddressCard extends StatelessWidget { - final String address; - final String network; - - const _WalletAddressCard({required this.address, required this.network}); - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.all(AppSpacing.md), - decoration: BoxDecoration( - color: context.colors.surfaceContainerHigh, - borderRadius: BorderRadius.circular(AppRadius.md), - border: Border.all(color: context.colors.outlineVariant.withValues(alpha: 0.3)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text( - address, - style: AppTextStyles.bodyMedium(context).copyWith( - fontFamily: 'monospace', - ), - ), - ), - GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: address)); - ToastUtils.show('地址已复制到剪贴板'); - }, - child: Container( - padding: EdgeInsets.all(AppSpacing.xs), - decoration: BoxDecoration( - color: context.colors.primary.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(AppRadius.sm), - ), - child: Icon(LucideIcons.copy, - size: 16, color: context.colors.primary), - ), - ), - ], - ), - SizedBox(height: AppSpacing.sm), - Text( - '网络: $network', - style: AppTextStyles.bodySmall(context), - ), - ], - ), - ); - } -} - /// 盈亏统计小卡片 class _ProfitStatCard extends StatelessWidget { final String label; - final double? value; + final double value; final Color upColor; final Color downColor; final VoidCallback? onTap; @@ -918,9 +634,8 @@ class _ProfitStatCard extends StatelessWidget { @override Widget build(BuildContext context) { - final hasValue = value != null; - final isProfit = (value ?? 0) >= 0; - final color = hasValue ? (isProfit ? upColor : downColor) : context.colors.onSurfaceVariant; + final isProfit = value >= 0; + final color = isProfit ? upColor : downColor; return GestureDetector( onTap: onTap, @@ -928,14 +643,10 @@ class _ProfitStatCard extends StatelessWidget { child: Container( padding: EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm + 2), decoration: BoxDecoration( - color: hasValue - ? (isProfit ? upColor : downColor).withValues(alpha: 0.06) - : context.colors.surfaceContainerHigh.withValues(alpha: 0.5), + color: color.withValues(alpha: 0.06), borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( - color: hasValue - ? (isProfit ? upColor : downColor).withValues(alpha: 0.12) - : context.colors.outlineVariant.withValues(alpha: 0.1), + color: color.withValues(alpha: 0.12), ), ), child: Column( @@ -944,9 +655,7 @@ class _ProfitStatCard extends StatelessWidget { Row( children: [ Icon( - hasValue - ? (isProfit ? LucideIcons.trendingUp : LucideIcons.trendingDown) - : LucideIcons.minus, + isProfit ? LucideIcons.trendingUp : LucideIcons.trendingDown, size: 11, color: color.withValues(alpha: 0.7), ), @@ -954,7 +663,7 @@ class _ProfitStatCard extends StatelessWidget { Text( label, style: AppTextStyles.bodySmall(context).copyWith( - fontWeight: FontWeight.w400, // w500 → w400 + fontWeight: FontWeight.w400, color: color.withValues(alpha: 0.8), ), ), @@ -962,11 +671,9 @@ class _ProfitStatCard extends StatelessWidget { ), SizedBox(height: AppSpacing.xs), Text( - hasValue - ? '${isProfit ? '+' : ''}${value!.toStringAsFixed(2)}' - : '--', + '${isProfit ? '+' : ''}${value.toStringAsFixed(2)}', style: AppTextStyles.numberMedium(context).copyWith( - fontWeight: FontWeight.w600, // bold → w600 + fontWeight: FontWeight.w600, color: color, ), ), diff --git a/flutter_monisuo/lib/ui/pages/orders/fund_order_card.dart b/flutter_monisuo/lib/ui/pages/orders/fund_order_card.dart index 997cba7..711d1ff 100644 --- a/flutter_monisuo/lib/ui/pages/orders/fund_order_card.dart +++ b/flutter_monisuo/lib/ui/pages/orders/fund_order_card.dart @@ -30,7 +30,7 @@ class _FundOrderCard extends StatelessWidget { return AppColorScheme.muted; } } else { - // 提现状态: 1=待审批, 2=已完成, 3=已驳回, 4=已取消, 5=待财务审核 + // 提现状态: 1=待审批, 2=已出款, 3=已驳回, 4=已取消, 5=待财务审核 switch (status) { case 1: return AppColorScheme.warning; @@ -117,20 +117,49 @@ class _FundOrderCard extends StatelessWidget { ], ), SizedBox(height: AppSpacing.sm), - if (!isDeposit && order.fee != null) ...[ - Row( - children: [ - Text('手续费(10%): ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), - Text('-${order.fee} USDT', style: AppTextStyles.bodyMedium(context)), - ], - ), - SizedBox(height: AppSpacing.xs), - Row( - children: [ - Text('应收款: ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), - Text('${order.receivableAmount ?? "0"} USDT', style: AppTextStyles.bodyMedium(context).copyWith(fontWeight: FontWeight.w700)), - ], - ), + if (!isDeposit) ...[ + if (order.fee != null) ...[ + Row( + children: [ + Text('手续费(10%): ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), + Text('-${order.fee} USDT', style: AppTextStyles.bodyMedium(context)), + ], + ), + SizedBox(height: AppSpacing.xs), + ], + if (order.receivableAmount != null) ...[ + Row( + children: [ + Text('到账金额: ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), + Text('${order.receivableAmount} USDT', style: AppTextStyles.bodyMedium(context).copyWith(fontWeight: FontWeight.w700)), + ], + ), + SizedBox(height: AppSpacing.xs), + ], + if (order.network != null) ...[ + Row( + children: [ + Text('提现网络: ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), + Text(order.network!, style: AppTextStyles.bodyMedium(context)), + ], + ), + SizedBox(height: AppSpacing.xs), + ], + if (order.walletAddress != null) ...[ + Row( + children: [ + Text('提现地址: ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), + Expanded( + child: Text( + order.walletAddress!, + style: AppTextStyles.bodyMedium(context).copyWith(fontSize: 11), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + SizedBox(height: AppSpacing.xs), + ], SizedBox(height: AppSpacing.sm), ], Row( diff --git a/flutter_monisuo/lib/ui/pages/orders/fund_orders_list.dart b/flutter_monisuo/lib/ui/pages/orders/fund_orders_list.dart index ce0c385..ad9f3ac 100644 --- a/flutter_monisuo/lib/ui/pages/orders/fund_orders_list.dart +++ b/flutter_monisuo/lib/ui/pages/orders/fund_orders_list.dart @@ -142,7 +142,7 @@ class _FundOrderCardContent extends StatelessWidget { case 1: return '待审批'; case 2: - return '已完成'; + return '已出款'; case 3: return '已驳回'; case 4: @@ -188,6 +188,50 @@ class _FundOrderCardContent extends StatelessWidget { ], ), SizedBox(height: AppSpacing.sm), + if (!isDeposit) ...[ + if (order.fee != null) ...[ + Row( + children: [ + Text('手续费(10%): ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), + Text('-${order.fee} USDT', style: AppTextStyles.bodyMedium(context)), + ], + ), + SizedBox(height: AppSpacing.xs), + ], + if (order.receivableAmount != null) ...[ + Row( + children: [ + Text('到账金额: ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), + Text('${order.receivableAmount} USDT', style: AppTextStyles.bodyMedium(context).copyWith(fontWeight: FontWeight.w700)), + ], + ), + SizedBox(height: AppSpacing.xs), + ], + if (order.network != null) ...[ + Row( + children: [ + Text('提现网络: ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), + Text(order.network!, style: AppTextStyles.bodyMedium(context)), + ], + ), + SizedBox(height: AppSpacing.xs), + ], + if (order.walletAddress != null) ...[ + Row( + children: [ + Text('提现地址: ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), + Expanded( + child: Text( + order.walletAddress!, + style: AppTextStyles.bodyMedium(context).copyWith(fontSize: 11), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + SizedBox(height: AppSpacing.xs), + ], + ], Row( children: [ Text('订单号: ', style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.mutedForeground)), diff --git a/flutter_monisuo/lib/ui/pages/orders/fund_orders_page.dart b/flutter_monisuo/lib/ui/pages/orders/fund_orders_page.dart index e9c6f6f..6ac9a49 100644 --- a/flutter_monisuo/lib/ui/pages/orders/fund_orders_page.dart +++ b/flutter_monisuo/lib/ui/pages/orders/fund_orders_page.dart @@ -322,12 +322,11 @@ class _FundOrdersPageState extends State { children: [ _buildDetailRow('订单号', order.orderNo), const SizedBox(height: AppSpacing.sm - AppSpacing.xs), - if (order.walletAddress != null) ...[ - _buildDetailRow( - '网络', - order.remark.isNotEmpty ? order.remark : '-', - ), + if (order.network != null) ...[ + _buildDetailRow('网络', order.network!), const SizedBox(height: AppSpacing.sm - AppSpacing.xs), + ], + if (order.walletAddress != null) ...[ _buildDetailRow( '地址', _truncateAddress(order.walletAddress!), @@ -340,9 +339,6 @@ class _FundOrdersPageState extends State { ), ), const SizedBox(height: AppSpacing.sm - AppSpacing.xs), - ] else if (order.remark.isNotEmpty) ...[ - _buildDetailRow('网络', order.remark), - const SizedBox(height: AppSpacing.sm - AppSpacing.xs), ], if (order.fee != null && !order.isDeposit) ...[ _buildDetailRow('手续费', '${order.fee}%'), diff --git a/monisuo-admin/src/pages/monisuo/finance-orders.vue b/monisuo-admin/src/pages/monisuo/finance-orders.vue index f7e7d88..6f50427 100644 --- a/monisuo-admin/src/pages/monisuo/finance-orders.vue +++ b/monisuo-admin/src/pages/monisuo/finance-orders.vue @@ -299,6 +299,11 @@ function copyToClipboard(text: string) {
{{ currentOrder.network }}
+ +
发起时间
{{ currentOrder.createTime }}
diff --git a/monisuo-admin/src/pages/monisuo/orders.vue b/monisuo-admin/src/pages/monisuo/orders.vue index 3d45f08..dbacbf3 100644 --- a/monisuo-admin/src/pages/monisuo/orders.vue +++ b/monisuo-admin/src/pages/monisuo/orders.vue @@ -144,7 +144,7 @@ function getStatusVariant(order: OrderFund): 'default' | 'secondary' | 'destruct else { // 提现 if (status === 1) return 'default' // 待审批 - if (status === 2) return 'default' // 已完成 + if (status === 2) return 'default' // 已出款 if (status === 5) return 'secondary' // 待财务审核 return 'destructive' // 已驳回/已取消 } @@ -422,10 +422,10 @@ function copyToClipboard(text: string) { 待付款/待审批 - 待确认/已完成 + 待确认/已出款 - 已完成 + 已完成/已驳回 已驳回 diff --git a/sql/init.sql b/sql/init.sql index c945a33..89909c1 100644 --- a/sql/init.sql +++ b/sql/init.sql @@ -290,8 +290,14 @@ ALTER TABLE `order_fund` ADD COLUMN `wallet_id` bigint(20) DEFAULT NULL COMMENT '钱包ID' AFTER `amount`, ADD COLUMN `wallet_address` varchar(255) DEFAULT NULL COMMENT '钱包地址(充值地址/提现地址)' AFTER `wallet_id`, ADD COLUMN `withdraw_contact` varchar(100) DEFAULT NULL COMMENT '提现联系方式' AFTER `wallet_address`, +ADD COLUMN `network` varchar(20) DEFAULT NULL COMMENT '提现网络类型(TRC20/ERC20等)' AFTER `withdraw_contact`, +ADD COLUMN `fee` decimal(18,2) DEFAULT NULL COMMENT '手续费' AFTER `network`, +ADD COLUMN `receivable_amount` decimal(18,2) DEFAULT NULL COMMENT '到账金额' AFTER `fee`, ADD COLUMN `pay_time` datetime DEFAULT NULL COMMENT '用户打款时间' AFTER `remark`, ADD COLUMN `confirm_time` datetime DEFAULT NULL COMMENT '确认/审批时间' AFTER `pay_time`, +ADD COLUMN `finance_admin_id` bigint(20) DEFAULT NULL COMMENT '财务审批管理员ID' AFTER `confirm_time`, +ADD COLUMN `finance_admin_name` varchar(50) DEFAULT NULL COMMENT '财务审批管理员名称' AFTER `finance_admin_id`, +ADD COLUMN `finance_approve_time` datetime DEFAULT NULL COMMENT '财务审批时间' AFTER `finance_admin_name`, ADD INDEX `idx_wallet_id` (`wallet_id`); SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/main/java/com/it/rattan/monisuo/entity/OrderFund.java b/src/main/java/com/it/rattan/monisuo/entity/OrderFund.java index 159c7e2..8fe42a2 100644 --- a/src/main/java/com/it/rattan/monisuo/entity/OrderFund.java +++ b/src/main/java/com/it/rattan/monisuo/entity/OrderFund.java @@ -53,7 +53,7 @@ public class OrderFund implements Serializable { /** 提现联系方式 */ private String withdrawContact; - /** 状态: 充值-1待付款2待确认3已完成4已驳回5已取消6充值失败; 提现-1待审批2已完成3已驳回4已取消5待财务审核 */ + /** 状态: 充值-1待付款2待确认3已完成4已驳回5已取消6充值失败; 提现-1待审批2已出款3已驳回4已取消5待财务审核 */ private Integer status; /** 用户确认打款时间 */ diff --git a/src/main/java/com/it/rattan/monisuo/service/AssetService.java b/src/main/java/com/it/rattan/monisuo/service/AssetService.java index ced97bf..b3c527d 100644 --- a/src/main/java/com/it/rattan/monisuo/service/AssetService.java +++ b/src/main/java/com/it/rattan/monisuo/service/AssetService.java @@ -90,8 +90,11 @@ public class AssetService { } result.put("tradeBalance", tradeBalance); - result.put("totalAsset", fundBalance.add(tradeBalance)); - result.put("totalProfit", totalValue.subtract(totalCost)); + BigDecimal totalAsset = fundBalance.add(tradeBalance); + result.put("totalAsset", totalAsset); + // 总盈亏 = 总资产 - 累计充值(用户净投入为累计充值,总资产超出部分即为盈利) + BigDecimal totalDeposit = fund.getTotalDeposit() != null ? fund.getTotalDeposit() : BigDecimal.ZERO; + result.put("totalProfit", totalAsset.subtract(totalDeposit)); return result; }