import 'package:flutter/material.dart'; import '../../../../app/theme/app_colors.dart'; import '../../../../app/router.dart'; import '../../../../app/i18n/app_localizations.dart'; /// 财务管理页面 /// /// 法币展示,不暴露链上稳定币细节 /// 包含:销售收入、Breakage收入、手续费、保证金、冻结款、提现、对账报表 class FinancePage extends StatelessWidget { const FinancePage({super.key}); @override Widget build(BuildContext context) { return DefaultTabController( length: 3, child: Scaffold( appBar: AppBar( title: Text(context.t('finance_title')), actions: [ IconButton( icon: const Icon(Icons.download_rounded), onPressed: () => _showExportDialog(context), ), ], bottom: TabBar( tabs: [ Tab(text: context.t('finance_tab_overview')), Tab(text: context.t('finance_tab_transactions')), Tab(text: context.t('finance_tab_reconciliation')), ], ), ), body: const TabBarView( children: [ _OverviewTab(), _TransactionDetailTab(), _ReconciliationTab(), ], ), ), ); } void _showExportDialog(BuildContext context) { showDialog( context: context, builder: (ctx) => SimpleDialog( title: Text(context.t('finance_export_title')), children: [ SimpleDialogOption(onPressed: () => Navigator.pop(ctx), child: Text(context.t('finance_export_csv'))), SimpleDialogOption(onPressed: () => Navigator.pop(ctx), child: Text(context.t('finance_export_excel'))), SimpleDialogOption(onPressed: () => Navigator.pop(ctx), child: Text(context.t('finance_export_pdf'))), ], ), ); } } class _OverviewTab extends StatelessWidget { const _OverviewTab(); @override Widget build(BuildContext context) { return SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( children: [ // Balance Card Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: AppColors.primaryGradient, borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(context.t('finance_withdrawable'), style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: 0.7))), const SizedBox(height: 4), const Text('\$42,300.00', style: TextStyle(fontSize: 32, fontWeight: FontWeight.w700, color: Colors.white)), const SizedBox(height: 16), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { // TODO: Show withdrawal dialog or navigate to withdrawal flow }, style: ElevatedButton.styleFrom( backgroundColor: Colors.white, foregroundColor: AppColors.primary, ), child: Text(context.t('finance_withdraw')), ), ), ], ), ), const SizedBox(height: 20), // Financial Stats _buildFinanceStatsGrid(context), const SizedBox(height: 20), // Guarantee Fund _buildGuaranteeFundCard(context), const SizedBox(height: 20), // Revenue Trend Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.borderLight), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(context.t('finance_revenue_trend'), style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600)), const SizedBox(height: 16), Container( height: 160, decoration: BoxDecoration( color: AppColors.gray50, borderRadius: BorderRadius.circular(8), ), child: Center(child: Text(context.t('finance_revenue_chart'), style: const TextStyle(color: AppColors.textTertiary))), ), ], ), ), ], ), ); } Widget _buildFinanceStatsGrid(BuildContext context) { final stats = [ (context.t('finance_sales_income'), '\$125,800', AppColors.success), (context.t('finance_breakage_income'), '\$8,200', AppColors.info), (context.t('finance_platform_fee'), '-\$1,510', AppColors.error), (context.t('finance_pending_settlement'), '\$15,400', AppColors.warning), (context.t('finance_withdrawn'), '\$66,790', AppColors.textSecondary), (context.t('finance_total_income'), '\$132,490', AppColors.primary), ]; return GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 2, ), itemCount: stats.length, itemBuilder: (context, index) { final (label, value, color) = stats[index]; return Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.borderLight), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: const TextStyle(fontSize: 12, color: AppColors.textSecondary)), Text(value, style: TextStyle(fontSize: 17, fontWeight: FontWeight.w700, color: color)), ], ), ); }, ); } Widget _buildGuaranteeFundCard(BuildContext context) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.borderLight), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.shield_rounded, color: AppColors.info, size: 20), const SizedBox(width: 8), Text(context.t('finance_guarantee_title'), style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600)), ], ), const SizedBox(height: 16), _buildRow(context.t('finance_guarantee_deposit'), '\$10,000'), _buildRow(context.t('finance_frozen_sales'), '\$5,200'), _buildRow(context.t('finance_frozen_ratio'), '20%'), const SizedBox(height: 12), SwitchListTile( title: Text(context.t('finance_auto_freeze'), style: const TextStyle(fontSize: 14)), subtitle: Text(context.t('finance_auto_freeze_desc')), value: true, onChanged: (_) { // TODO: Toggle auto-freeze setting }, activeColor: AppColors.primary, contentPadding: EdgeInsets.zero, ), ], ), ); } Widget _buildRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: const TextStyle(fontSize: 13, color: AppColors.textSecondary)), Text(value, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500)), ], ), ); } } class _TransactionDetailTab extends StatelessWidget { const _TransactionDetailTab(); @override Widget build(BuildContext context) { final transactions = [ ('售出 ¥25 礼品卡 x5', '+\$106.25', '今天 14:32', AppColors.success), ('核销结算 ¥100 购物券 x2', '+\$200.00', '今天 12:15', AppColors.success), ('平台手续费', '-\$3.19', '今天 14:32', AppColors.error), ('退款 ¥25 礼品卡', '-\$21.25', '今天 10:08', AppColors.warning), ('售出 ¥50 生活券 x3', '+\$127.50', '昨天 18:45', AppColors.success), ('提现至银行账户', '-\$5,000.00', '昨天 16:00', AppColors.info), ]; return ListView.separated( padding: const EdgeInsets.all(20), itemCount: transactions.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (context, index) { final (desc, amount, time, color) = transactions[index]; return ListTile( contentPadding: const EdgeInsets.symmetric(vertical: 6), title: Text(desc, style: const TextStyle(fontSize: 14)), subtitle: Text(time, style: const TextStyle(fontSize: 12, color: AppColors.textTertiary)), trailing: Text( amount, style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: color), ), ); }, ); } } class _ReconciliationTab extends StatelessWidget { const _ReconciliationTab(); @override Widget build(BuildContext context) { final reports = [ ('2026年1月对账单', '总收入: \$28,450 | 总支出: \$3,210', '已生成'), ('2025年12月对账单', '总收入: \$32,100 | 总支出: \$4,080', '已生成'), ('2025年11月对账单', '总收入: \$25,800 | 总支出: \$2,900', '已生成'), ]; return ListView( padding: const EdgeInsets.all(20), children: [ // Generate New OutlinedButton.icon( onPressed: () { // TODO: Trigger reconciliation report generation }, icon: const Icon(Icons.add_rounded), label: Text(context.t('finance_generate_report')), style: OutlinedButton.styleFrom( minimumSize: const Size(double.infinity, 48), ), ), const SizedBox(height: 20), ...reports.map((r) { final (title, summary, status) = r; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.surface, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.borderLight), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600)), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: AppColors.successLight, borderRadius: BorderRadius.circular(999), ), child: Text(status, style: const TextStyle(fontSize: 11, color: AppColors.success)), ), ], ), const SizedBox(height: 6), Text(summary, style: const TextStyle(fontSize: 12, color: AppColors.textSecondary)), const SizedBox(height: 12), Row( children: [ TextButton.icon( onPressed: () { // TODO: Navigate to reconciliation detail view }, icon: const Icon(Icons.visibility_rounded, size: 16), label: Text(context.t('view')), ), TextButton.icon( onPressed: () { // TODO: Export reconciliation report }, icon: const Icon(Icons.download_rounded, size: 16), label: Text(context.t('export')), ), ], ), ], ), ); }), ], ); } }