import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:provider/provider.dart'; import '../../../providers/asset_provider.dart'; /// 资产页面 - 使用 shadcn_ui 现代化设计 class AssetPage extends StatefulWidget { const AssetPage({super.key}); @override State createState() => _AssetPageState(); } class _AssetPageState extends State with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; int _activeTab = 0; // 0=资金账户, 1=交易账户 // 颜色常量 static const upColor = Color(0xFF00C853); static const downColor = Color(0xFFFF5252); @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { _loadData(); }); } void _loadData() { context.read().refreshAll(); } @override Widget build(BuildContext context) { super.build(context); final theme = ShadTheme.of(context); return Scaffold( backgroundColor: theme.colorScheme.background, body: Consumer( builder: (context, provider, _) { return RefreshIndicator( onRefresh: provider.refreshAll, color: theme.colorScheme.primary, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.all(16), child: Column( children: [ _buildAssetCard(provider), const SizedBox(height: 16), _buildAccountTabs(), const SizedBox(height: 16), _activeTab == 0 ? _buildFundAccount(provider) : _buildTradeAccount(provider), ], ), ), ); }, ), ); } Widget _buildAssetCard(AssetProvider provider) { final theme = ShadTheme.of(context); final overview = provider.overview; // 自定义渐变色 const gradientColors = [ Color(0xFF00D4AA), Color(0xFF00B894), ]; return Container( width: double.infinity, padding: const EdgeInsets.all(24), decoration: BoxDecoration( gradient: const LinearGradient( colors: gradientColors, begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(20), ), child: Column( children: [ Text( '总资产估值(USDT)', style: theme.textTheme.small.copyWith(color: Colors.white70), ), const SizedBox(height: 8), Text( overview?.totalAsset ?? '0.00', style: theme.textTheme.h1.copyWith( fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( LucideIcons.trendingUp, color: Colors.white70, size: 16, ), const SizedBox(width: 4), Text( '总盈亏: ${overview?.totalProfit ?? '0.00'} USDT', style: theme.textTheme.small.copyWith(color: Colors.white70), ), ], ), ], ), ); } Widget _buildAccountTabs() { final theme = ShadTheme.of(context); return Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: theme.colorScheme.card, borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Expanded( child: GestureDetector( onTap: () => setState(() => _activeTab = 0), child: Container( padding: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: _activeTab == 0 ? theme.colorScheme.primary : Colors.transparent, borderRadius: BorderRadius.circular(8), ), child: Center( child: Text( '资金账户', style: TextStyle( color: _activeTab == 0 ? Colors.white : theme.colorScheme.mutedForeground, fontWeight: _activeTab == 0 ? FontWeight.w600 : FontWeight.normal, ), ), ), ), ), ), Expanded( child: GestureDetector( onTap: () => setState(() => _activeTab = 1), child: Container( padding: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: _activeTab == 1 ? theme.colorScheme.primary : Colors.transparent, borderRadius: BorderRadius.circular(8), ), child: Center( child: Text( '交易账户', style: TextStyle( color: _activeTab == 1 ? Colors.white : theme.colorScheme.mutedForeground, fontWeight: _activeTab == 1 ? FontWeight.w600 : FontWeight.normal, ), ), ), ), ), ), ], ), ); } Widget _buildFundAccount(AssetProvider provider) { final theme = ShadTheme.of(context); final fund = provider.fundAccount; return ShadCard( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'USDT余额', style: theme.textTheme.muted, ), const SizedBox(height: 8), Text( fund?.balance ?? '0.00', style: theme.textTheme.h2.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 24), Row( children: [ Expanded( child: ShadButton( backgroundColor: const Color(0xFF00C853), onPressed: () => _showDepositDialog(provider), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(LucideIcons.plus, size: 18, color: Colors.white), const SizedBox(width: 4), const Text('充值'), ], ), ), ), const SizedBox(width: 12), Expanded( child: ShadButton( backgroundColor: const Color(0xFFFF9800), onPressed: () => _showWithdrawDialog(provider), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(LucideIcons.minus, size: 18, color: Colors.white), const SizedBox(width: 4), const Text('提现'), ], ), ), ), const SizedBox(width: 12), Expanded( child: ShadButton.outline( onPressed: () => _showTransferDialog(provider), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(LucideIcons.arrowRightLeft, size: 18), const SizedBox(width: 4), const Text('划转'), ], ), ), ), ], ), ], ), ); } Widget _buildTradeAccount(AssetProvider provider) { final theme = ShadTheme.of(context); final holdings = provider.holdings; return ShadCard( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '持仓列表', style: theme.textTheme.large.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), if (holdings.isEmpty) Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( children: [ Icon( LucideIcons.wallet, size: 48, color: theme.colorScheme.mutedForeground, ), const SizedBox(height: 12), Text( '暂无持仓', style: theme.textTheme.muted, ), ], ), ), ) else ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: holdings.length, separatorBuilder: (_, __) => Divider( color: theme.colorScheme.border, height: 1, ), itemBuilder: (context, index) { final holding = holdings[index]; return _buildHoldingItem(holding); }, ), ], ), ); } Widget _buildHoldingItem(holding) { final theme = ShadTheme.of(context); return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( children: [ CircleAvatar( radius: 20, backgroundColor: theme.colorScheme.primary.withValues(alpha: 0.1), child: Text( holding.coinCode.substring(0, 1), style: TextStyle( color: theme.colorScheme.primary, fontWeight: FontWeight.bold, ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( holding.coinCode, style: theme.textTheme.large.copyWith( fontWeight: FontWeight.w600, ), ), Text( '数量: ${holding.quantity}', style: theme.textTheme.muted.copyWith(fontSize: 12), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '${holding.currentValue} USDT', style: theme.textTheme.small, ), Text( holding.formattedProfitRate, style: TextStyle( color: holding.isProfit ? upColor : downColor, fontSize: 12, ), ), ], ), ], ), ); } void _showDepositDialog(AssetProvider provider) { _showActionDialog( title: '充值', hint: '请输入充值金额(USDT)', onSubmit: (amount) async { final response = await provider.deposit(amount: amount); if (mounted) { _showResult(response.success ? '申请成功' : '申请失败', response.message); } }, ); } void _showWithdrawDialog(AssetProvider provider) { _showActionDialog( title: '提现', hint: '请输入提现金额(USDT)', onSubmit: (amount) async { final response = await provider.withdraw(amount: amount); if (mounted) { _showResult(response.success ? '申请成功' : '申请失败', response.message); } }, ); } void _showTransferDialog(AssetProvider provider) { final controller = TextEditingController(); final formKey = GlobalKey(); int direction = 1; showShadDialog( context: context, builder: (context) => StatefulBuilder( builder: (context, setState) => ShadDialog( title: const Text('划转'), child: Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ShadButton.outline( size: ShadButtonSize.sm, onPressed: () => setState(() => direction = 1), child: Row( children: [ if (direction == 1) Icon(LucideIcons.check, size: 14) else const SizedBox(width: 14), const SizedBox(width: 4), const Text('资金→交易'), ], ), ), const SizedBox(width: 8), ShadButton.outline( size: ShadButtonSize.sm, onPressed: () => setState(() => direction = 2), child: Row( children: [ if (direction == 2) Icon(LucideIcons.check, size: 14) else const SizedBox(width: 14), const SizedBox(width: 4), const Text('交易→资金'), ], ), ), ], ), const SizedBox(height: 16), ShadForm( key: formKey, child: ShadInputFormField( id: 'amount', controller: controller, placeholder: const Text('请输入划转金额(USDT)'), keyboardType: const TextInputType.numberWithOptions(decimal: true), validator: (value) { if (value == null || value.isEmpty) { return '请输入金额'; } final amount = double.tryParse(value); if (amount == null || amount <= 0) { return '请输入有效金额'; } return null; }, ), ), ], ), actions: [ ShadButton.outline( child: const Text('取消'), onPressed: () => Navigator.of(context).pop(), ), ShadButton( child: const Text('确认'), onPressed: () async { if (formKey.currentState!.saveAndValidate()) { Navigator.of(context).pop(); final response = await provider.transfer( direction: direction, amount: controller.text, ); if (mounted) { _showResult( response.success ? '划转成功' : '划转失败', response.message, ); } } }, ), ], ), ), ); } void _showActionDialog({ required String title, required String hint, required Function(String) onSubmit, }) { final controller = TextEditingController(); final formKey = GlobalKey(); showShadDialog( context: context, builder: (context) => ShadDialog( title: Text(title), child: ShadForm( key: formKey, child: ShadInputFormField( id: 'amount', controller: controller, placeholder: Text(hint), keyboardType: const TextInputType.numberWithOptions(decimal: true), validator: (value) { if (value == null || value.isEmpty) { return '请输入金额'; } final amount = double.tryParse(value); if (amount == null || amount <= 0) { return '请输入有效金额'; } return null; }, ), ), actions: [ ShadButton.outline( child: const Text('取消'), onPressed: () => Navigator.of(context).pop(), ), ShadButton( child: const Text('确认'), onPressed: () async { if (formKey.currentState!.saveAndValidate()) { Navigator.of(context).pop(); onSubmit(controller.text); } }, ), ], ), ); } void _showResult(String title, String? message) { final theme = ShadTheme.of(context); showShadDialog( context: context, builder: (context) => ShadDialog.alert( title: Text(title), description: message != null ? Text(message) : null, actions: [ ShadButton( child: const Text('确定'), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } }