import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/theme/app_theme.dart'; import '../../providers/asset_provider.dart'; import '../../providers/auth_provider.dart'; import '../../services/asset_service.dart'; /// 资产数字展示:整数不带小数点,否则保留两位 String fmtAssets(double v) => v == v.roundToDouble() ? v.toInt().toString() : v.toStringAsFixed(2); /// 收益资产页(《03-接口文档》第 9 章): /// 资产余额(10 资产 = 1 元)/ 累计收益·提现 / 收益明细(筛选 + 触底分页)/ 提现入口 class AssetsScreen extends ConsumerWidget { const AssetsScreen({super.key}); static const List> _filters = [ {'label': '全部', 'value': null}, {'label': '充值返利', 'value': 1}, {'label': '观看收益', 'value': 2}, {'label': '点赞收益', 'value': 3}, {'label': '提现', 'value': 4}, {'label': '提现退回', 'value': 5}, {'label': '返利扣回', 'value': 6}, {'label': '后台调整', 'value': 7}, ]; @override Widget build(BuildContext context, WidgetRef ref) { final isLoggedIn = ref.watch(authProvider).isLoggedIn; if (!isLoggedIn) { return Scaffold( appBar: AppBar(title: const Text('收益资产')), body: _GuestGuide(onLogin: () => context.push('/login')), ); } final state = ref.watch(assetProvider); return Scaffold( appBar: AppBar(title: const Text('收益资产')), body: state.isLoading && state.wallet == null ? const Center(child: CircularProgressIndicator()) : state.loadFailed && state.wallet == null ? _LoadFailed( onRetry: () => ref.read(assetProvider.notifier).load(), ) : RefreshIndicator( onRefresh: () => ref.read(assetProvider.notifier).load(), child: NotificationListener( onNotification: (n) { if (n.metrics.pixels >= n.metrics.maxScrollExtent - 200) { ref.read(assetProvider.notifier).loadMore(); } return false; }, child: ListView( padding: const EdgeInsets.all(16), children: [ _BalanceCard(wallet: state.wallet), const SizedBox(height: 12), // 提现入口 SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () => context .push('/assets/withdraw') .then((_) => ref.read(assetProvider.notifier).load()), style: ElevatedButton.styleFrom( minimumSize: const Size(0, 44), ), child: const Text('申请提现'), ), ), if (state.wallet?.hasPendingWithdraw ?? false) ...[ const SizedBox(height: 8), const Text( '有一笔提现审核中,审核完成后可再次申请', textAlign: TextAlign.center, style: TextStyle( color: AppColors.textWeak, fontSize: 12, ), ), ], const SizedBox(height: 20), // 明细筛选 SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: _filters.map((f) { final active = state.bizType == f['value']; return Padding( padding: const EdgeInsets.only(right: 8), child: ChoiceChip( label: Text(f['label'] as String), selected: active, onSelected: (_) => ref .read(assetProvider.notifier) .setBizType(f['value'] as int?), selectedColor: AppColors.primary, backgroundColor: AppColors.surface, labelStyle: TextStyle( color: active ? Colors.white : AppColors.textSecondary, ), ), ); }).toList(), ), ), const SizedBox(height: 8), if (state.records.isEmpty) const Padding( padding: EdgeInsets.symmetric(vertical: 40), child: Center( child: Text('暂无收益明细', style: TextStyle(color: AppColors.textWeak)), ), ) else ...[ for (final r in state.records) _RecordTile(record: r), if (state.hasMore) const Padding( padding: EdgeInsets.all(16), child: Center( child: SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ), ), ), ], ], ), ), ), ); } } /// 资产卡:余额 + 折合 + 累计 class _BalanceCard extends StatelessWidget { const _BalanceCard({required this.wallet}); final AssetWallet? wallet; @override Widget build(BuildContext context) { final w = wallet; return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: AppColors.goldGradient, borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '资产余额', style: TextStyle(color: Colors.black54, fontSize: 13), ), const SizedBox(height: 4), Text( fmtAssets(w?.assets ?? 0), style: const TextStyle( color: Colors.black, fontSize: 32, fontWeight: FontWeight.w800, ), ), Text( '约 ¥${(w?.assetsValueYuan ?? 0).toStringAsFixed(2)}(10 资产 = 1 元)', style: const TextStyle(color: Colors.black54, fontSize: 12), ), const SizedBox(height: 16), Row( children: [ Expanded( child: _Stat(label: '累计收益', value: fmtAssets(w?.totalEarned ?? 0)), ), Expanded( child: _Stat(label: '累计提现', value: fmtAssets(w?.totalWithdrawn ?? 0)), ), Expanded( child: _Stat( label: '提现门槛', value: '${w?.minWithdrawAssets ?? 100} 资产', ), ), ], ), ], ), ); } } class _Stat extends StatelessWidget { const _Stat({required this.label, required this.value}); final String label; final String value; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( value, style: const TextStyle( color: Colors.black, fontSize: 15, fontWeight: FontWeight.w700, ), ), Text( label, style: const TextStyle(color: Colors.black54, fontSize: 11), ), ], ); } } class _RecordTile extends StatelessWidget { const _RecordTile({required this.record}); final AssetRecord record; @override Widget build(BuildContext context) { final isExpense = record.isExpense; return Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(record.bizTypeLabel, style: const TextStyle(fontSize: 15)), if (record.remark.isNotEmpty) Text( record.remark, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.textWeak, fontSize: 12, ), ), Text( record.createdAt, style: const TextStyle( color: AppColors.textWeak, fontSize: 11, ), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '${isExpense ? '' : '+'}${fmtAssets(record.changeAmount)}', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w700, color: isExpense ? Colors.white : AppColors.gold, ), ), Text( '余额 ${fmtAssets(record.balanceAfter)}', style: const TextStyle( color: AppColors.textWeak, fontSize: 11, ), ), ], ), ], ), ); } } class _GuestGuide extends StatelessWidget { const _GuestGuide({required this.onLogin}); final VoidCallback onLogin; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.savings_outlined, size: 64, color: AppColors.textWeak), const SizedBox(height: 12), const Text('登录后查看收益资产', style: TextStyle(color: AppColors.textSecondary)), const SizedBox(height: 16), ElevatedButton( onPressed: onLogin, style: ElevatedButton.styleFrom( minimumSize: const Size(160, 44), ), child: const Text('去登录'), ), ], ), ); } } class _LoadFailed extends StatelessWidget { const _LoadFailed({required this.onRetry}); final VoidCallback onRetry; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('加载失败', style: TextStyle(color: AppColors.textSecondary)), const SizedBox(height: 12), TextButton(onPressed: onRetry, child: const Text('点击重试')), ], ), ); } }