fix: 完整还原提交 f69f05c 的所有修改

- 还原 main_page.dart: 恢复首页Tab导航
- 还原 asset_page.dart: 恢复原始资产页面设计
- 撤销3月24日的页面重构,恢复应用正常功能
This commit is contained in:
2026-03-25 09:23:24 +08:00
parent 8b42c9624e
commit 8ce4648ab0

View File

@@ -11,7 +11,7 @@ import '../../components/glass_panel.dart';
import '../../components/neon_glow.dart'; import '../../components/neon_glow.dart';
import '../orders/fund_orders_page.dart'; import '../orders/fund_orders_page.dart';
/// 资产页面 - 钱包风格 /// 资产页面 - Material Design 3 风格
class AssetPage extends StatefulWidget { class AssetPage extends StatefulWidget {
const AssetPage({super.key}); const AssetPage({super.key});
@@ -20,6 +20,8 @@ class AssetPage extends StatefulWidget {
} }
class _AssetPageState extends State<AssetPage> with AutomaticKeepAliveClientMixin { class _AssetPageState extends State<AssetPage> with AutomaticKeepAliveClientMixin {
int _activeTab = 0;
@override @override
bool get wantKeepAlive => true; bool get wantKeepAlive => true;
@@ -52,22 +54,16 @@ class _AssetPageState extends State<AssetPage> with AutomaticKeepAliveClientMixi
physics: const AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
padding: AppSpacing.pagePadding, padding: AppSpacing.pagePadding,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// 1. 总资产估值卡片 _TabSelector(
_TotalAssetCard(overview: provider.overview), tabs: const ['资金账户', '交易账户'],
SizedBox(height: AppSpacing.lg), selectedIndex: _activeTab,
onChanged: (index) => setState(() => _activeTab = index),
// 2. 操作按钮 ),
_ActionButtons(provider: provider), SizedBox(height: AppSpacing.md),
SizedBox(height: AppSpacing.lg), _activeTab == 0
? _FundAccountCard(provider: provider)
// 3. 资产组合 : _TradeAccountCard(holdings: provider.holdings),
_AssetComposition(provider: provider),
SizedBox(height: AppSpacing.lg),
// 4. 代币列表
_TokenList(holdings: provider.holdings),
], ],
), ),
), ),
@@ -78,11 +74,11 @@ class _AssetPageState extends State<AssetPage> with AutomaticKeepAliveClientMixi
} }
} }
/// 资产估值卡片 /// 资产总览卡片 - Material Design 3 风格
class _TotalAssetCard extends StatelessWidget { class _AssetCard extends StatelessWidget {
final dynamic overview; final dynamic overview;
const _TotalAssetCard({required this.overview}); const _AssetCard({required this.overview});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -91,7 +87,7 @@ class _TotalAssetCard extends StatelessWidget {
return Container( return Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.all(AppSpacing.xl), padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.sm),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: AppColorScheme.assetCardGradient, gradient: AppColorScheme.assetCardGradient,
borderRadius: BorderRadius.circular(AppRadius.xl), borderRadius: BorderRadius.circular(AppRadius.xl),
@@ -103,71 +99,221 @@ class _TotalAssetCard extends StatelessWidget {
], ],
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'总资产估值', 'PORTFOLIO VALUE',
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 10,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w700,
letterSpacing: 0.5, letterSpacing: 0.2,
color: Colors.white.withOpacity(0.7), color: Colors.white.withOpacity(0.7),
), ),
), ),
SizedBox(height: AppSpacing.sm), SizedBox(height: AppSpacing.sm),
Row( Text(
crossAxisAlignment: CrossAxisAlignment.end, '\$${overview?.totalAsset ?? '0.00'}',
children: [ style: GoogleFonts.spaceGrotesk(
Text( fontSize: 36,
'\$${overview?.totalAsset ?? '0.00'}', fontWeight: FontWeight.bold,
style: GoogleFonts.spaceGrotesk( color: Colors.white,
fontSize: 40, ),
fontWeight: FontWeight.bold, ),
color: Colors.white, SizedBox(height: AppSpacing.md),
Container(
padding: EdgeInsets.symmetric(
horizontal: AppSpacing.md,
vertical: AppSpacing.xs + AppSpacing.xs,
),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(AppRadius.full),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
LucideIcons.trendingUp,
color: Colors.white.withOpacity(0.7),
size: 14,
), ),
), SizedBox(width: AppSpacing.xs),
SizedBox(width: AppSpacing.sm), Text(
Padding( '总盈亏: ${overview?.totalProfit ?? '0.00'} USDT',
padding: EdgeInsets.only(bottom: 8),
child: Text(
'USDT',
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 12,
color: Colors.white.withOpacity(0.7), color: Colors.white.withOpacity(0.7),
), ),
), ),
],
),
),
],
),
);
}
}
/// Tab 选择器 - Material Design 3 风格
class _TabSelector extends StatelessWidget {
final List<String> tabs;
final int selectedIndex;
final ValueChanged<int> onChanged;
const _TabSelector({
required this.tabs,
required this.selectedIndex,
required this.onChanged,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
padding: EdgeInsets.all(AppSpacing.xs),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(AppRadius.lg),
),
child: Row(
children: tabs.asMap().entries.map((entry) {
final index = entry.key;
final label = entry.value;
final isSelected = index == selectedIndex;
return Expanded(
child: GestureDetector(
onTap: () => onChanged(index),
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm + AppSpacing.xs),
decoration: BoxDecoration(
color: isSelected ? colorScheme.primary : Colors.transparent,
borderRadius: BorderRadius.circular(AppRadius.md),
boxShadow: isSelected
? [
BoxShadow(
color: colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08),
blurRadius: 10,
),
]
: null,
),
child: Center(
child: Text(
label,
style: TextStyle(
color: isSelected ? colorScheme.onPrimary : colorScheme.onSurfaceVariant,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
),
),
),
),
),
);
}).toList(),
),
);
}
}
/// 资金账户卡片 - Glass Panel 风格
class _FundAccountCard extends StatelessWidget {
final AssetProvider provider;
const _FundAccountCard({required this.provider});
@override
Widget build(BuildContext context) {
final fund = provider.fundAccount;
final overview = provider.overview;
final colorScheme = Theme.of(context).colorScheme;
// 优先使用fund数据如果为null则使用overview的fundBalance
final displayBalance = fund?.balance ?? overview?.fundBalance ?? '0.00';
return GlassPanel(
padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.xs),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'USDT 余额',
style: TextStyle(
fontSize: 12,
color: colorScheme.onSurfaceVariant,
),
),
GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const FundOrdersPage()),
),
child: Row(
children: [
Text(
'充提记录',
style: TextStyle(
color: colorScheme.primary,
fontSize: 12,
),
),
Icon(
LucideIcons.chevronRight,
size: 14,
color: colorScheme.primary,
),
],
),
), ),
], ],
), ),
SizedBox(height: AppSpacing.md), SizedBox(height: AppSpacing.sm),
Text(
displayBalance,
style: GoogleFonts.spaceGrotesk(
fontSize: 28,
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
SizedBox(height: AppSpacing.lg),
Row( Row(
children: [ children: [
Container( Expanded(
padding: EdgeInsets.symmetric( child: NeonButton(
horizontal: AppSpacing.sm, text: '充值',
vertical: AppSpacing.xs, type: NeonButtonType.tertiary,
icon: Icons.add,
onPressed: () => _showDepositDialog(context),
height: 44,
showGlow: false,
), ),
decoration: BoxDecoration( ),
color: Colors.white.withOpacity(0.15), SizedBox(width: AppSpacing.sm),
borderRadius: BorderRadius.circular(AppRadius.full), Expanded(
child: NeonButton(
text: '提现',
type: NeonButtonType.secondary,
icon: Icons.remove,
onPressed: () => _showWithdrawDialog(context, fund?.balance),
height: 44,
showGlow: false,
), ),
child: Row( ),
mainAxisSize: MainAxisSize.min, SizedBox(width: AppSpacing.sm),
children: [ Expanded(
Icon( child: NeonButton(
LucideIcons.trendingUp, text: '划转',
color: Colors.white.withOpacity(0.9), type: NeonButtonType.outline,
size: 12, icon: Icons.swap_horiz,
), onPressed: () => _showTransferDialog(context),
SizedBox(width: AppSpacing.xs), height: 44,
Text( showGlow: false,
'今日收益: ${overview?.totalProfit ?? '0.00'} USDT',
style: TextStyle(
fontSize: 11,
color: Colors.white.withOpacity(0.9),
),
),
],
), ),
), ),
], ],
@@ -178,264 +324,46 @@ class _TotalAssetCard extends StatelessWidget {
} }
} }
/// 操作按钮 /// 交易账户卡片 - Glass Panel 风格
class _ActionButtons extends StatelessWidget { class _TradeAccountCard extends StatelessWidget {
final AssetProvider provider;
const _ActionButtons({required this.provider});
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: _ActionButton(
icon: LucideIcons.download,
label: '充币',
onTap: () => _showDepositDialog(context),
),
),
SizedBox(width: AppSpacing.sm),
Expanded(
child: _ActionButton(
icon: LucideIcons.upload,
label: '提币',
onTap: () => _showWithdrawDialog(context, provider.fundAccount?.balance),
),
),
SizedBox(width: AppSpacing.sm),
Expanded(
child: _ActionButton(
icon: LucideIcons.arrowLeftRight,
label: '划转',
onTap: () => _showTransferDialog(context),
),
),
],
);
}
}
/// 操作按钮项
class _ActionButton extends StatelessWidget {
final IconData icon;
final String label;
final VoidCallback onTap;
const _ActionButton({
required this.icon,
required this.label,
required this.onTap,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return GestureDetector(
onTap: onTap,
child: Container(
padding: EdgeInsets.symmetric(vertical: AppSpacing.md),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.md),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.2),
),
),
child: Column(
children: [
Icon(
icon,
color: colorScheme.primary,
size: 24,
),
SizedBox(height: AppSpacing.xs),
Text(
label,
style: TextStyle(
fontSize: 12,
color: colorScheme.onSurface,
fontWeight: FontWeight.w500,
),
),
],
),
),
);
}
}
/// 资产组合
class _AssetComposition extends StatelessWidget {
final AssetProvider provider;
const _AssetComposition({required this.provider});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final fund = provider.fundAccount;
final overview = provider.overview;
final fundBalance = fund?.balance ?? overview?.fundBalance ?? '0.00';
final tradeBalance = overview?.tradeBalance ?? '0';
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'资产组合',
style: GoogleFonts.spaceGrotesk(
fontSize: 16,
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
SizedBox(height: AppSpacing.md),
Row(
children: [
Expanded(
child: _AssetCard(
icon: LucideIcons.wallet,
title: '资金账户',
amount: '$fundBalance USDT',
onTap: () {},
),
),
SizedBox(width: AppSpacing.sm),
Expanded(
child: _AssetCard(
icon: LucideIcons.trendingUp,
title: '交易账户',
amount: '$tradeBalance USDT',
onTap: () {},
),
),
],
),
],
);
}
}
/// 资产卡片
class _AssetCard extends StatelessWidget {
final IconData icon;
final String title;
final String amount;
final VoidCallback onTap;
const _AssetCard({
required this.icon,
required this.title,
required this.amount,
required this.onTap,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return GestureDetector(
onTap: onTap,
child: Container(
padding: EdgeInsets.all(AppSpacing.md),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.md),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.2),
),
),
child: Column(
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: colorScheme.primary.withOpacity(0.1),
shape: BoxShape.circle,
),
child: Center(
child: Icon(
icon,
color: colorScheme.primary,
size: 20,
),
),
),
SizedBox(height: AppSpacing.sm),
Text(
title,
style: TextStyle(
fontSize: 11,
color: colorScheme.onSurfaceVariant,
),
),
SizedBox(height: AppSpacing.xs),
Text(
amount,
style: GoogleFonts.spaceGrotesk(
fontSize: 14,
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
],
),
),
);
}
}
/// 资产列表
class _TokenList extends StatelessWidget {
final List holdings; final List holdings;
const _TokenList({required this.holdings}); const _TradeAccountCard({required this.holdings});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme; final colorScheme = Theme.of(context).colorScheme;
// 对持仓进行排序USDT 放在最上面 return GlassPanel(
final sortedHoldings = List.from(holdings); padding: AppSpacing.cardPadding,
sortedHoldings.sort((a, b) { child: Column(
final codeA = (a.coinCode ?? a['coinCode'] ?? '').toString().toUpperCase(); crossAxisAlignment: CrossAxisAlignment.start,
final codeB = (b.coinCode ?? b['coinCode'] ?? '').toString().toUpperCase(); children: [
// USDT 排在最前面 Text(
if (codeA == 'USDT') return -1; '持仓列表',
if (codeB == 'USDT') return 1; style: GoogleFonts.spaceGrotesk(
return 0; fontSize: 16,
}); fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'资产列表',
style: GoogleFonts.spaceGrotesk(
fontSize: 16,
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
SizedBox(height: AppSpacing.md),
if (sortedHoldings.isEmpty)
_EmptyState(icon: LucideIcons.wallet, message: '暂无持仓')
else
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: sortedHoldings.length,
separatorBuilder: (_, __) => Divider(
height: 1,
color: colorScheme.outlineVariant.withOpacity(0.2),
), ),
itemBuilder: (context, index) => _TokenItem(holding: sortedHoldings[index]),
), ),
], SizedBox(height: AppSpacing.md),
if (holdings.isEmpty)
const _EmptyState(icon: LucideIcons.wallet, message: '暂无持仓')
else
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: holdings.length,
separatorBuilder: (_, __) => Container(
margin: EdgeInsets.only(left: 56),
height: 1,
color: AppColorScheme.glassPanelBorder,
),
itemBuilder: (context, index) => _HoldingItem(holding: holdings[index]),
),
],
),
); );
} }
} }
@@ -473,11 +401,11 @@ class _EmptyState extends StatelessWidget {
} }
} }
/// 代币 /// 持仓
class _TokenItem extends StatelessWidget { class _HoldingItem extends StatelessWidget {
final dynamic holding; final dynamic holding;
const _TokenItem({required this.holding}); const _HoldingItem({required this.holding});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -485,12 +413,12 @@ class _TokenItem extends StatelessWidget {
final isDark = Theme.of(context).brightness == Brightness.dark; final isDark = Theme.of(context).brightness == Brightness.dark;
return Padding( return Padding(
padding: EdgeInsets.symmetric(vertical: AppSpacing.md), padding: EdgeInsets.symmetric(vertical: AppSpacing.sm),
child: Row( child: Row(
children: [ children: [
Container( Container(
width: 44, width: 40,
height: 44, height: 40,
decoration: BoxDecoration( decoration: BoxDecoration(
color: colorScheme.primary.withOpacity(0.1), color: colorScheme.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(AppRadius.md), borderRadius: BorderRadius.circular(AppRadius.md),
@@ -501,50 +429,25 @@ class _TokenItem extends StatelessWidget {
style: TextStyle( style: TextStyle(
color: colorScheme.primary, color: colorScheme.primary,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 18,
), ),
), ),
), ),
), ),
SizedBox(width: AppSpacing.md), SizedBox(width: AppSpacing.sm + AppSpacing.xs),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row(
children: [
Text(
holding.coinCode,
style: GoogleFonts.spaceGrotesk(
fontSize: 15,
fontWeight: FontWeight.w600,
color: colorScheme.onSurface,
),
),
SizedBox(width: AppSpacing.sm),
Container(
padding: EdgeInsets.symmetric(
horizontal: AppSpacing.xs,
vertical: 2,
),
decoration: BoxDecoration(
color: AppColorScheme.getUpColor(isDark).withOpacity(0.1),
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Text(
'+5.2%',
style: TextStyle(
fontSize: 10,
color: AppColorScheme.getUpColor(isDark),
fontWeight: FontWeight.w600,
),
),
),
],
),
SizedBox(height: AppSpacing.xs),
Text( Text(
holding.quantity, holding.coinCode,
style: GoogleFonts.spaceGrotesk(
fontSize: 14,
fontWeight: FontWeight.w600,
color: colorScheme.onSurface,
),
),
Text(
'数量: ${holding.quantity}',
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: colorScheme.onSurfaceVariant, color: colorScheme.onSurfaceVariant,
@@ -558,13 +461,11 @@ class _TokenItem extends StatelessWidget {
children: [ children: [
Text( Text(
'${holding.currentValue} USDT', '${holding.currentValue} USDT',
style: GoogleFonts.spaceGrotesk( style: TextStyle(
fontSize: 15, fontSize: 12,
fontWeight: FontWeight.w600,
color: colorScheme.onSurface, color: colorScheme.onSurface,
), ),
), ),
SizedBox(height: AppSpacing.xs),
Text( Text(
holding.formattedProfitRate, holding.formattedProfitRate,
style: TextStyle( style: TextStyle(
@@ -608,7 +509,7 @@ void _showDepositDialog(BuildContext context) {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'充币', 'Deposit (充值)',
style: GoogleFonts.spaceGrotesk( style: GoogleFonts.spaceGrotesk(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -949,7 +850,7 @@ void _showWithdrawDialog(BuildContext context, String? balance) {
), ),
SizedBox(width: AppSpacing.sm), SizedBox(width: AppSpacing.sm),
Text( Text(
'', '现 (Withdraw)',
style: GoogleFonts.spaceGrotesk( style: GoogleFonts.spaceGrotesk(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -1011,8 +912,8 @@ void _showWithdrawDialog(BuildContext context, String? balance) {
ShadInputFormField( ShadInputFormField(
id: 'amount', id: 'amount',
controller: amountController, controller: amountController,
label: const Text('金额'), label: const Text('金额'),
placeholder: const Text('请输入提金额(USDT)'), placeholder: const Text('请输入提金额(USDT)'),
keyboardType: const TextInputType.numberWithOptions(decimal: true), keyboardType: const TextInputType.numberWithOptions(decimal: true),
validator: Validators.amount, validator: Validators.amount,
), ),
@@ -1021,8 +922,8 @@ void _showWithdrawDialog(BuildContext context, String? balance) {
id: 'address', id: 'address',
controller: addressController, controller: addressController,
label: const Text('目标地址'), label: const Text('目标地址'),
placeholder: const Text('请输入提地址'), placeholder: const Text('请输入提地址'),
validator: (v) => Validators.required(v, '地址'), validator: (v) => Validators.required(v, '地址'),
), ),
SizedBox(height: AppSpacing.md), SizedBox(height: AppSpacing.md),
ShadInputFormField( ShadInputFormField(