337 lines
12 KiB
Dart
337 lines
12 KiB
Dart
import 'package:flutter/material.dart';
|
||
import '../../../../app/theme/app_colors.dart';
|
||
|
||
/// 财务管理页面
|
||
///
|
||
/// 法币展示,不暴露链上稳定币细节
|
||
/// 包含:销售收入、Breakage收入、手续费、保证金、冻结款、提现、对账报表
|
||
class FinancePage extends StatelessWidget {
|
||
const FinancePage({super.key});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return DefaultTabController(
|
||
length: 3,
|
||
child: Scaffold(
|
||
appBar: AppBar(
|
||
title: const Text('财务管理'),
|
||
actions: [
|
||
IconButton(
|
||
icon: const Icon(Icons.download_rounded),
|
||
onPressed: () => _showExportDialog(context),
|
||
),
|
||
],
|
||
bottom: const TabBar(
|
||
tabs: [
|
||
Tab(text: '概览'),
|
||
Tab(text: '交易明细'),
|
||
Tab(text: '对账报表'),
|
||
],
|
||
),
|
||
),
|
||
body: const TabBarView(
|
||
children: [
|
||
_OverviewTab(),
|
||
_TransactionDetailTab(),
|
||
_ReconciliationTab(),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showExportDialog(BuildContext context) {
|
||
showDialog(
|
||
context: context,
|
||
builder: (ctx) => SimpleDialog(
|
||
title: const Text('导出数据'),
|
||
children: [
|
||
SimpleDialogOption(onPressed: () => Navigator.pop(ctx), child: const Text('导出 CSV')),
|
||
SimpleDialogOption(onPressed: () => Navigator.pop(ctx), child: const Text('导出 Excel')),
|
||
SimpleDialogOption(onPressed: () => Navigator.pop(ctx), child: const Text('导出 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('可提现余额', 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: () {},
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: Colors.white,
|
||
foregroundColor: AppColors.primary,
|
||
),
|
||
child: const Text('提现'),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
const SizedBox(height: 20),
|
||
|
||
// Financial Stats
|
||
_buildFinanceStatsGrid(),
|
||
const SizedBox(height: 20),
|
||
|
||
// Guarantee Fund
|
||
_buildGuaranteeFundCard(),
|
||
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: [
|
||
const Text('收入趋势', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600)),
|
||
const SizedBox(height: 16),
|
||
Container(
|
||
height: 160,
|
||
decoration: BoxDecoration(
|
||
color: AppColors.gray50,
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
child: const Center(child: Text('月度收入趋势图', style: TextStyle(color: AppColors.textTertiary))),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _buildFinanceStatsGrid() {
|
||
final stats = [
|
||
('销售收入', '\$125,800', AppColors.success),
|
||
('Breakage收入', '\$8,200', AppColors.info),
|
||
('平台手续费', '-\$1,510', AppColors.error),
|
||
('待结算', '\$15,400', AppColors.warning),
|
||
('已提现', '\$66,790', AppColors.textSecondary),
|
||
('总收入', '\$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() {
|
||
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: [
|
||
const Row(
|
||
children: [
|
||
Icon(Icons.shield_rounded, color: AppColors.info, size: 20),
|
||
SizedBox(width: 8),
|
||
Text('保证金与冻结款', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600)),
|
||
],
|
||
),
|
||
const SizedBox(height: 16),
|
||
_buildRow('已缴纳保证金', '\$10,000'),
|
||
_buildRow('冻结销售款', '\$5,200'),
|
||
_buildRow('冻结比例', '20%'),
|
||
const SizedBox(height: 12),
|
||
SwitchListTile(
|
||
title: const Text('自动冻结销售款', style: TextStyle(fontSize: 14)),
|
||
subtitle: const Text('开启后自动冻结20%销售额以提升信用'),
|
||
value: true,
|
||
onChanged: (_) {},
|
||
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: () {},
|
||
icon: const Icon(Icons.add_rounded),
|
||
label: const Text('生成新对账单'),
|
||
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: () {},
|
||
icon: const Icon(Icons.visibility_rounded, size: 16),
|
||
label: const Text('查看'),
|
||
),
|
||
TextButton.icon(
|
||
onPressed: () {},
|
||
icon: const Icon(Icons.download_rounded, size: 16),
|
||
label: const Text('导出'),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}),
|
||
],
|
||
);
|
||
}
|
||
}
|