feat(ui): 优化所有页面使用现代设计系统
- 使用 AppSpacing 替换硬编码间距 - 使用 AppRadius 替换硬编码圆角 - 使用 withValues(alpha:) 替换 withOpacity - 优化 login_page, home_page, market_page, trade_page, asset_page, mine_page Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,8 @@ import 'package:flutter/services.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/constants/app_colors.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../providers/asset_provider.dart';
|
||||
import '../../shared/ui_constants.dart';
|
||||
import '../orders/fund_orders_page.dart';
|
||||
@@ -45,17 +47,17 @@ class _AssetPageState extends State<AssetPage> with AutomaticKeepAliveClientMixi
|
||||
color: theme.colorScheme.primary,
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.pagePadding,
|
||||
child: Column(
|
||||
children: [
|
||||
_AssetCard(overview: provider.overview),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_TabSelector(
|
||||
tabs: const ['资金账户', '交易账户'],
|
||||
selectedIndex: _activeTab,
|
||||
onChanged: (index) => setState(() => _activeTab = index),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_activeTab == 0
|
||||
? _FundAccountCard(provider: provider)
|
||||
: _TradeAccountCard(holdings: provider.holdings),
|
||||
@@ -81,14 +83,14 @@ class _AssetCard extends StatelessWidget {
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(24),
|
||||
padding: EdgeInsets.all(AppSpacing.lg),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
colors: AppColors.gradientColors,
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -96,7 +98,7 @@ class _AssetCard extends StatelessWidget {
|
||||
'总资产估值(USDT)',
|
||||
style: theme.textTheme.small.copyWith(color: Colors.white70),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
overview?.totalAsset ?? '0.00',
|
||||
style: theme.textTheme.h1.copyWith(
|
||||
@@ -104,12 +106,12 @@ class _AssetCard extends StatelessWidget {
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(LucideIcons.trendingUp, color: Colors.white70, size: 16),
|
||||
const SizedBox(width: 4),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
Text(
|
||||
'总盈亏: ${overview?.totalProfit ?? '0.00'} USDT',
|
||||
style: theme.textTheme.small.copyWith(color: Colors.white70),
|
||||
@@ -139,10 +141,10 @@ class _TabSelector extends StatelessWidget {
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
padding: EdgeInsets.all(AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.card,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
child: Row(
|
||||
children: tabs.asMap().entries.map((entry) {
|
||||
@@ -154,10 +156,10 @@ class _TabSelector extends StatelessWidget {
|
||||
child: GestureDetector(
|
||||
onTap: () => onChanged(index),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? theme.colorScheme.primary : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
@@ -189,7 +191,7 @@ class _FundAccountCard extends StatelessWidget {
|
||||
final fund = provider.fundAccount;
|
||||
|
||||
return ShadCard(
|
||||
padding: const EdgeInsets.all(20),
|
||||
padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.xs),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -211,15 +213,15 @@ class _FundAccountCard extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Text(fund?.balance ?? '0.00', style: theme.textTheme.h2.copyWith(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _ActionButton(label: '充值', icon: LucideIcons.plus, color: AppColors.deposit, onTap: () => _showDepositDialog(context))),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: _ActionButton(label: '提现', icon: LucideIcons.minus, color: AppColors.withdraw, onTap: () => _showWithdrawDialog(context, fund?.balance))),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: _ActionButton(label: '充值', icon: LucideIcons.plus, color: AppColorScheme.success, onTap: () => _showDepositDialog(context))),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Expanded(child: _ActionButton(label: '提现', icon: LucideIcons.minus, color: AppColorScheme.warning, onTap: () => _showWithdrawDialog(context, fund?.balance))),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Expanded(child: _ActionButton.outline(label: '划转', icon: LucideIcons.arrowRightLeft, onTap: () => _showTransferDialog(context))),
|
||||
],
|
||||
),
|
||||
@@ -256,7 +258,7 @@ class _ActionButton extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(icon, size: 18, color: isOutline ? null : Colors.white),
|
||||
const SizedBox(width: 4),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
Text(label),
|
||||
],
|
||||
);
|
||||
@@ -278,12 +280,12 @@ class _TradeAccountCard extends StatelessWidget {
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return ShadCard(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('持仓列表', style: theme.textTheme.large.copyWith(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
if (holdings.isEmpty)
|
||||
const _EmptyState(icon: LucideIcons.wallet, message: '暂无持仓')
|
||||
else
|
||||
@@ -313,11 +315,11 @@ class _EmptyState extends StatelessWidget {
|
||||
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
padding: EdgeInsets.all(AppSpacing.xl),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(icon, size: 48, color: theme.colorScheme.mutedForeground),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
Text(message, style: theme.textTheme.muted),
|
||||
],
|
||||
),
|
||||
@@ -337,7 +339,7 @@ class _HoldingItem extends StatelessWidget {
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm),
|
||||
child: Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
@@ -348,7 +350,7 @@ class _HoldingItem extends StatelessWidget {
|
||||
style: TextStyle(color: theme.colorScheme.primary, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -365,7 +367,7 @@ class _HoldingItem extends StatelessWidget {
|
||||
Text(
|
||||
holding.formattedProfitRate,
|
||||
style: TextStyle(
|
||||
color: holding.isProfit ? AppColors.up : AppColors.down,
|
||||
color: holding.isProfit ? AppColorScheme.up : AppColorScheme.down,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
@@ -434,13 +436,13 @@ void _showDepositResultDialog(BuildContext context, Map<String, dynamic> data) {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('订单号: $orderNo', style: const TextStyle(fontSize: 12)),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Text('充值金额: $amount USDT', style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
const Text('请向以下地址转账:', style: TextStyle(fontSize: 12)),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
_WalletAddressCard(address: walletAddress, network: walletNetwork),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
const Text('转账完成后请点击"已打款"按钮确认', style: TextStyle(fontSize: 12, color: Colors.orange)),
|
||||
],
|
||||
),
|
||||
@@ -474,10 +476,10 @@ class _WalletAddressCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
padding: EdgeInsets.all(AppSpacing.sm + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[100],
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -499,7 +501,7 @@ class _WalletAddressCard extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Text('网络: $network', style: const TextStyle(fontSize: 12, color: Colors.grey)),
|
||||
],
|
||||
),
|
||||
@@ -526,7 +528,7 @@ void _showWithdrawDialog(BuildContext context, String? balance) {
|
||||
children: [
|
||||
if (balance != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
padding: EdgeInsets.only(bottom: AppSpacing.sm + AppSpacing.xs),
|
||||
child: Text('可用余额: $balance USDT', style: const TextStyle(color: Colors.grey)),
|
||||
),
|
||||
ShadInputFormField(
|
||||
@@ -536,14 +538,14 @@ void _showWithdrawDialog(BuildContext context, String? balance) {
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
validator: Validators.amount,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
ShadInputFormField(
|
||||
id: 'address',
|
||||
controller: addressController,
|
||||
placeholder: const Text('请输入提现地址'),
|
||||
validator: (v) => Validators.required(v, '提现地址'),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
ShadInputFormField(
|
||||
id: 'contact',
|
||||
controller: contactController,
|
||||
@@ -593,7 +595,7 @@ void _showTransferDialog(BuildContext context) {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
@@ -602,7 +604,7 @@ void _showTransferDialog(BuildContext context) {
|
||||
isSelected: direction == 1,
|
||||
onTap: () => setState(() => direction = 1),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
_DirectionButton(
|
||||
label: '交易→资金',
|
||||
isSelected: direction == 2,
|
||||
@@ -610,7 +612,7 @@ void _showTransferDialog(BuildContext context) {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
ShadForm(
|
||||
key: formKey,
|
||||
child: ShadInputFormField(
|
||||
@@ -661,7 +663,7 @@ class _DirectionButton extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
if (isSelected) const Icon(LucideIcons.check, size: 14) else const SizedBox(width: 14),
|
||||
const SizedBox(width: 4),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
Text(label),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../providers/auth_provider.dart';
|
||||
import '../main/main_page.dart';
|
||||
import 'register_page.dart';
|
||||
@@ -29,7 +30,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: _maxFormWidth),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
padding: EdgeInsets.all(AppSpacing.lg),
|
||||
child: ShadForm(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
@@ -37,13 +38,13 @@ class _LoginPageState extends State<LoginPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildHeader(theme),
|
||||
const SizedBox(height: 48),
|
||||
SizedBox(height: AppSpacing.xxl),
|
||||
_buildUsernameField(),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_buildPasswordField(),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
_buildLoginButton(),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_buildRegisterLink(theme),
|
||||
],
|
||||
),
|
||||
@@ -62,13 +63,13 @@ class _LoginPageState extends State<LoginPage> {
|
||||
size: _logoSize,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
Text(
|
||||
'模拟所',
|
||||
style: theme.textTheme.h1,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
'虚拟货币模拟交易平台',
|
||||
style: theme.textTheme.muted,
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/constants/app_colors.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../providers/asset_provider.dart';
|
||||
import '../../../providers/auth_provider.dart';
|
||||
import '../../shared/ui_constants.dart';
|
||||
@@ -44,22 +46,22 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
|
||||
color: theme.colorScheme.primary,
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.pagePadding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
_Header(),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(height: AppSpacing.lg + AppSpacing.sm),
|
||||
_AssetOverviewCard(overview: provider.overview),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_QuickActions(
|
||||
onDeposit: _showDeposit,
|
||||
onWithdraw: _showWithdraw,
|
||||
onTransfer: _showTransfer,
|
||||
onTrade: _navigateToTrade,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
_HoldingsList(holdings: provider.holdings),
|
||||
],
|
||||
),
|
||||
@@ -96,14 +98,14 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
validator: Validators.amount,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
ShadInputFormField(
|
||||
id: 'address',
|
||||
placeholder: const Text('请输入提现地址'),
|
||||
controller: addressController,
|
||||
validator: (v) => Validators.required(v, '提现地址'),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
ShadInputFormField(
|
||||
id: 'contact',
|
||||
placeholder: const Text('联系方式(可选)'),
|
||||
@@ -187,7 +189,7 @@ class _Header extends StatelessWidget {
|
||||
return Row(
|
||||
children: [
|
||||
_Avatar(text: user?.avatarText),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -196,7 +198,7 @@ class _Header extends StatelessWidget {
|
||||
'你好,${user?.username ?? '用户'}',
|
||||
style: theme.textTheme.large.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Text('欢迎来到模拟所', style: theme.textTheme.muted),
|
||||
],
|
||||
),
|
||||
@@ -241,25 +243,25 @@ class _AssetOverviewCard extends StatelessWidget {
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(20),
|
||||
padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.sm),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
colors: AppColors.gradientColors,
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('总资产(USDT)', style: theme.textTheme.small.copyWith(color: Colors.white70)),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
overview?.totalAsset ?? '0.00',
|
||||
style: theme.textTheme.h2.copyWith(color: Colors.white, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(height: AppSpacing.lg + AppSpacing.sm),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@@ -286,7 +288,7 @@ class _AssetItem extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(label, style: const TextStyle(fontSize: 12, color: Colors.white70)),
|
||||
const SizedBox(height: 4),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Text(value, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Colors.white)),
|
||||
],
|
||||
);
|
||||
@@ -310,14 +312,14 @@ class _QuickActions extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ShadCard(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
_ActionButton(icon: LucideIcons.arrowDownToLine, text: '充值', color: AppColors.deposit, onTap: onDeposit),
|
||||
_ActionButton(icon: LucideIcons.arrowUpFromLine, text: '提现', color: AppColors.withdraw, onTap: onWithdraw),
|
||||
_ActionButton(icon: LucideIcons.arrowRightLeft, text: '划转', color: AppColors.trade, onTap: onTransfer),
|
||||
_ActionButton(icon: LucideIcons.trendingUp, text: '交易', color: AppColors.trade, onTap: onTrade),
|
||||
_ActionButton(icon: LucideIcons.arrowDownToLine, text: '充值', color: AppColorScheme.success, onTap: onDeposit),
|
||||
_ActionButton(icon: LucideIcons.arrowUpFromLine, text: '提现', color: AppColorScheme.warning, onTap: onWithdraw),
|
||||
_ActionButton(icon: LucideIcons.arrowRightLeft, text: '划转', color: AppColorScheme.info, onTap: onTransfer),
|
||||
_ActionButton(icon: LucideIcons.trendingUp, text: '交易', color: AppColorScheme.info, onTap: onTrade),
|
||||
],
|
||||
),
|
||||
).animate().fadeIn(duration: 500.ms, delay: 100.ms);
|
||||
@@ -349,10 +351,10 @@ class _ActionButton extends StatelessWidget {
|
||||
Container(
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(color: color.withOpacity(0.15), shape: BoxShape.circle),
|
||||
decoration: BoxDecoration(color: color.withValues(alpha: 0.15), shape: BoxShape.circle),
|
||||
child: Icon(icon, color: color, size: 22),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Text(text, style: TextStyle(fontSize: 12, color: theme.colorScheme.foreground)),
|
||||
],
|
||||
),
|
||||
@@ -371,7 +373,7 @@ class _HoldingsList extends StatelessWidget {
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return ShadCard(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -382,7 +384,7 @@ class _HoldingsList extends StatelessWidget {
|
||||
Icon(LucideIcons.chevronRight, color: theme.colorScheme.mutedForeground, size: 20),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
if (holdings.isEmpty)
|
||||
_EmptyHoldings()
|
||||
else
|
||||
@@ -401,13 +403,13 @@ class _EmptyHoldings extends StatelessWidget {
|
||||
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
padding: EdgeInsets.all(AppSpacing.xl),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(LucideIcons.wallet, size: 48, color: theme.colorScheme.mutedForeground),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
Text('暂无持仓', style: theme.textTheme.muted),
|
||||
const SizedBox(height: 4),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Text('快去交易吧~', style: theme.textTheme.muted.copyWith(fontSize: 12)),
|
||||
],
|
||||
),
|
||||
@@ -452,7 +454,7 @@ class _HoldingItem extends StatelessWidget {
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@@ -466,7 +468,7 @@ class _HoldingItem extends StatelessWidget {
|
||||
style: TextStyle(color: theme.colorScheme.primary, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -483,7 +485,7 @@ class _HoldingItem extends StatelessWidget {
|
||||
Text(
|
||||
holding.formattedProfitRate,
|
||||
style: TextStyle(
|
||||
color: holding.isProfit ? AppColors.up : AppColors.down,
|
||||
color: holding.isProfit ? AppColorScheme.up : AppColorScheme.down,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/constants/app_colors.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../data/models/coin.dart';
|
||||
import '../../../providers/market_provider.dart';
|
||||
|
||||
@@ -60,7 +62,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.pagePadding,
|
||||
child: ShadInput(
|
||||
controller: _searchController,
|
||||
placeholder: const Text('搜索币种...'),
|
||||
@@ -98,7 +100,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
|
||||
return Container(
|
||||
height: 44,
|
||||
margin: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||
margin: EdgeInsets.fromLTRB(AppSpacing.md, 0, AppSpacing.md, AppSpacing.md),
|
||||
child: Row(
|
||||
children: tabs.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
@@ -108,13 +110,13 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
return GestureDetector(
|
||||
onTap: () => provider.setTab(tab['key']!),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
margin: const EdgeInsets.only(right: 8),
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.lg + AppSpacing.xs, vertical: AppSpacing.sm + AppSpacing.xs),
|
||||
margin: EdgeInsets.only(right: AppSpacing.sm),
|
||||
decoration: BoxDecoration(
|
||||
color: isActive
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.card,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
),
|
||||
child: Text(
|
||||
tab['label']!,
|
||||
@@ -153,12 +155,12 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
size: 48,
|
||||
color: theme.colorScheme.destructive,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
Text(
|
||||
provider.error!,
|
||||
style: TextStyle(color: theme.colorScheme.destructive),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
ShadButton(
|
||||
onPressed: provider.loadCoins,
|
||||
child: const Text('重试'),
|
||||
@@ -179,7 +181,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
size: 48,
|
||||
color: theme.colorScheme.mutedForeground,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.sm + AppSpacing.xs),
|
||||
Text(
|
||||
'暂无数据',
|
||||
style: theme.textTheme.muted,
|
||||
@@ -193,7 +195,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
onRefresh: provider.refresh,
|
||||
color: theme.colorScheme.primary,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||
padding: EdgeInsets.fromLTRB(AppSpacing.md, 0, AppSpacing.md, AppSpacing.md),
|
||||
itemCount: coins.length,
|
||||
itemBuilder: (context, index) => _buildCoinItem(coins[index]),
|
||||
),
|
||||
@@ -204,9 +206,9 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
padding: EdgeInsets.only(bottom: AppSpacing.sm),
|
||||
child: ShadCard(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Row(
|
||||
children: [
|
||||
// 图标
|
||||
@@ -221,7 +223,7 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
// 名称
|
||||
Expanded(
|
||||
child: Column(
|
||||
@@ -242,15 +244,15 @@ class _MarketPageState extends State<MarketPage> with AutomaticKeepAliveClientMi
|
||||
),
|
||||
// 涨跌幅
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.sm + AppSpacing.xs, vertical: AppSpacing.xs + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.getChangeBackgroundColor(coin.isUp),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
color: getChangeBackgroundColor(coin.isUp),
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm + AppSpacing.xs),
|
||||
),
|
||||
child: Text(
|
||||
coin.formattedChange,
|
||||
style: TextStyle(
|
||||
color: AppColors.getChangeColor(coin.isUp),
|
||||
color: getChangeColor(coin.isUp),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../providers/auth_provider.dart';
|
||||
import '../../../providers/theme_provider.dart';
|
||||
import '../auth/login_page.dart';
|
||||
@@ -40,13 +42,13 @@ class _MinePageState extends State<MinePage> with AutomaticKeepAliveClientMixin
|
||||
body: Consumer<AuthProvider>(
|
||||
builder: (context, auth, _) {
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.pagePadding,
|
||||
child: Column(
|
||||
children: [
|
||||
_UserCard(user: auth.user),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_MenuList(onShowComingSoon: _showComingSoon, onShowAbout: _showAboutDialog),
|
||||
const SizedBox(height: 24),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
_LogoutButton(onLogout: () => _handleLogout(auth)),
|
||||
],
|
||||
),
|
||||
@@ -60,11 +62,11 @@ class _MinePageState extends State<MinePage> with AutomaticKeepAliveClientMixin
|
||||
showShadDialog(
|
||||
context: context,
|
||||
builder: (context) => ShadDialog.alert(
|
||||
title: const Row(
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(LucideIcons.construction, color: Color(0xFFFF9800), size: 20),
|
||||
SizedBox(width: 8),
|
||||
Text('功能开发中'),
|
||||
const Icon(LucideIcons.construction, color: Color(0xFFFF9800), size: 20),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
const Text('功能开发中'),
|
||||
],
|
||||
),
|
||||
description: Text('$feature功能正在开发中,敬请期待~'),
|
||||
@@ -87,7 +89,7 @@ class _MinePageState extends State<MinePage> with AutomaticKeepAliveClientMixin
|
||||
title: Row(
|
||||
children: [
|
||||
_AppLogo(radius: 20, fontSize: 20),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
const Text('模拟所'),
|
||||
],
|
||||
),
|
||||
@@ -96,9 +98,9 @@ class _MinePageState extends State<MinePage> with AutomaticKeepAliveClientMixin
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('虚拟货币模拟交易平台', style: theme.textTheme.muted),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_InfoRow(icon: LucideIcons.code, text: '版本: 1.0.0'),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
const _InfoRow(icon: LucideIcons.heart, text: 'Built with Flutter & shadcn_ui'),
|
||||
],
|
||||
),
|
||||
@@ -153,11 +155,11 @@ class _UserCard extends StatelessWidget {
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return ShadCard(
|
||||
padding: const EdgeInsets.all(20),
|
||||
padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.sm),
|
||||
child: Row(
|
||||
children: [
|
||||
_AppLogo(radius: 32, fontSize: 24, text: user?.avatarText),
|
||||
const SizedBox(width: 16),
|
||||
SizedBox(width: AppSpacing.md),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -166,7 +168,7 @@ class _UserCard extends StatelessWidget {
|
||||
user?.username ?? '未登录',
|
||||
style: theme.textTheme.h3.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
SizedBox(height: AppSpacing.sm - AppSpacing.xs),
|
||||
ShadBadge(
|
||||
backgroundColor: theme.colorScheme.primary.withValues(alpha: 0.2),
|
||||
child: Text(
|
||||
@@ -225,7 +227,7 @@ class _InfoRow extends StatelessWidget {
|
||||
return Row(
|
||||
children: [
|
||||
Icon(icon, size: 14, color: theme.colorScheme.mutedForeground),
|
||||
const SizedBox(width: 6),
|
||||
SizedBox(width: AppSpacing.sm - AppSpacing.xs),
|
||||
Text(text, style: theme.textTheme.muted.copyWith(fontSize: 12)),
|
||||
],
|
||||
);
|
||||
@@ -287,17 +289,17 @@ class _ThemeToggleTile extends StatelessWidget {
|
||||
return InkWell(
|
||||
onTap: () => themeProvider.toggleTheme(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm + AppSpacing.xs),
|
||||
child: Row(
|
||||
children: [
|
||||
_MenuIcon(icon: isDarkMode ? LucideIcons.moon : LucideIcons.sun),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('深色模式', style: theme.textTheme.small.copyWith(fontWeight: FontWeight.w500)),
|
||||
const SizedBox(height: 2),
|
||||
SizedBox(height: AppSpacing.xs / 2),
|
||||
Text(
|
||||
isDarkMode ? '当前:深色主题' : '当前:浅色主题',
|
||||
style: theme.textTheme.muted.copyWith(fontSize: 11),
|
||||
@@ -331,18 +333,18 @@ class _MenuItemTile extends StatelessWidget {
|
||||
return InkWell(
|
||||
onTap: item.onTap,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm + AppSpacing.xs),
|
||||
child: Row(
|
||||
children: [
|
||||
_MenuIcon(icon: item.icon),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(item.title, style: theme.textTheme.small.copyWith(fontWeight: FontWeight.w500)),
|
||||
if (item.subtitle != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
SizedBox(height: AppSpacing.xs / 2),
|
||||
Text(item.subtitle!, style: theme.textTheme.muted.copyWith(fontSize: 11)),
|
||||
],
|
||||
],
|
||||
@@ -371,7 +373,7 @@ class _MenuIcon extends StatelessWidget {
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md + AppSpacing.xs),
|
||||
),
|
||||
child: Icon(icon, size: 20, color: theme.colorScheme.primary),
|
||||
);
|
||||
@@ -391,12 +393,12 @@ class _LogoutButton extends StatelessWidget {
|
||||
height: 48,
|
||||
child: ShadButton.destructive(
|
||||
onPressed: onLogout,
|
||||
child: const Row(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(LucideIcons.logOut, size: 18),
|
||||
SizedBox(width: 8),
|
||||
Text('退出登录', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
const Icon(LucideIcons.logOut, size: 18),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
const Text('退出登录', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -343,19 +343,19 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
|
||||
}
|
||||
|
||||
void _confirmPay(OrderFund order) async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
final confirmed = await showShadDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
builder: (context) => ShadDialog.alert(
|
||||
title: const Text('确认已打款'),
|
||||
content: const Text('确认您已完成向指定地址的转账?'),
|
||||
description: const Text('确认您已完成向指定地址的转账?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
ShadButton.outline(
|
||||
child: const Text('取消'),
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
ShadButton(
|
||||
child: const Text('确认'),
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -372,20 +372,19 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
|
||||
}
|
||||
|
||||
void _cancelOrder(OrderFund order) async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
final confirmed = await showShadDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
builder: (context) => ShadDialog.alert(
|
||||
title: const Text('取消订单'),
|
||||
content: Text('确定要取消订单 ${order.orderNo} 吗?'),
|
||||
description: Text('确定要取消订单 ${order.orderNo} 吗?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
ShadButton.outline(
|
||||
child: const Text('返回'),
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
style: TextButton.styleFrom(foregroundColor: downColor),
|
||||
ShadButton.destructive(
|
||||
child: const Text('确定取消'),
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/constants/app_colors.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../data/models/coin.dart';
|
||||
import '../../../providers/market_provider.dart';
|
||||
import '../../../providers/asset_provider.dart';
|
||||
@@ -52,7 +54,7 @@ class _TradePageState extends State<TradePage> with AutomaticKeepAliveClientMixi
|
||||
body: Consumer2<MarketProvider, AssetProvider>(
|
||||
builder: (context, market, asset, _) {
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.pagePadding,
|
||||
child: ShadForm(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
@@ -65,9 +67,9 @@ class _TradePageState extends State<TradePage> with AutomaticKeepAliveClientMixi
|
||||
_priceController.text = coin.formattedPrice;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
if (_selectedCoin != null) _PriceCard(coin: _selectedCoin!),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_TradeForm(
|
||||
tradeType: _tradeType,
|
||||
selectedCoin: _selectedCoin,
|
||||
@@ -76,7 +78,7 @@ class _TradePageState extends State<TradePage> with AutomaticKeepAliveClientMixi
|
||||
tradeBalance: asset.overview?.tradeBalance,
|
||||
onTradeTypeChanged: (type) => setState(() => _tradeType = type),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
_TradeButton(
|
||||
isBuy: _tradeType == 0,
|
||||
coinCode: _selectedCoin?.code,
|
||||
@@ -129,7 +131,7 @@ class _TradePageState extends State<TradePage> with AutomaticKeepAliveClientMixi
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(LucideIcons.circleCheck, color: theme.colorScheme.primary, size: 24),
|
||||
const SizedBox(width: 8),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
const Text('交易成功'),
|
||||
],
|
||||
),
|
||||
@@ -170,11 +172,11 @@ class _CoinSelector extends StatelessWidget {
|
||||
}
|
||||
|
||||
return ShadCard(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Row(
|
||||
children: [
|
||||
_CoinAvatar(icon: selectedCoin?.displayIcon),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -183,7 +185,7 @@ class _CoinSelector extends StatelessWidget {
|
||||
selectedCoin != null ? '${selectedCoin!.code}/USDT' : '选择币种',
|
||||
style: theme.textTheme.large.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Text(selectedCoin?.name ?? '点击选择交易对', style: theme.textTheme.muted),
|
||||
],
|
||||
),
|
||||
@@ -225,10 +227,10 @@ class _PriceCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = ShadTheme.of(context);
|
||||
final color = coin.isUp ? AppColors.up : AppColors.down;
|
||||
final color = coin.isUp ? AppColorScheme.up : AppColorScheme.down;
|
||||
|
||||
return ShadCard(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@@ -236,15 +238,15 @@ class _PriceCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('最新价', style: theme.textTheme.muted),
|
||||
const SizedBox(height: 4),
|
||||
SizedBox(height: AppSpacing.xs),
|
||||
Text('\$${coin.formattedPrice}', style: theme.textTheme.h2.copyWith(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.sm + AppSpacing.xs, vertical: AppSpacing.xs + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: color.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
),
|
||||
child: Text(
|
||||
coin.formattedChange,
|
||||
@@ -280,7 +282,7 @@ class _TradeForm extends StatelessWidget {
|
||||
final theme = ShadTheme.of(context);
|
||||
|
||||
return ShadCard(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.cardPadding,
|
||||
child: Column(
|
||||
children: [
|
||||
// 买入/卖出切换
|
||||
@@ -288,7 +290,7 @@ class _TradeForm extends StatelessWidget {
|
||||
tradeType: tradeType,
|
||||
onChanged: onTradeTypeChanged,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(height: AppSpacing.lg + AppSpacing.xs),
|
||||
// 价格输入
|
||||
ShadInputFormField(
|
||||
id: 'price',
|
||||
@@ -296,13 +298,13 @@ class _TradeForm extends StatelessWidget {
|
||||
controller: priceController,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
placeholder: const Text('输入价格'),
|
||||
trailing: const Padding(
|
||||
padding: EdgeInsets.only(right: 8),
|
||||
child: Text('USDT'),
|
||||
trailing: Padding(
|
||||
padding: EdgeInsets.only(right: AppSpacing.sm),
|
||||
child: const Text('USDT'),
|
||||
),
|
||||
validator: Validators.price,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
// 数量输入
|
||||
ShadInputFormField(
|
||||
id: 'quantity',
|
||||
@@ -311,15 +313,15 @@ class _TradeForm extends StatelessWidget {
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
placeholder: const Text('输入数量'),
|
||||
trailing: Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
padding: EdgeInsets.only(right: AppSpacing.sm),
|
||||
child: Text(selectedCoin?.code ?? ''),
|
||||
),
|
||||
validator: Validators.quantity,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
// 交易金额
|
||||
_InfoRow(label: '交易金额', value: '${_calculateAmount()} USDT'),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
// 可用余额
|
||||
_InfoRow(label: '可用', value: '${tradeBalance ?? '0.00'} USDT'),
|
||||
],
|
||||
@@ -349,16 +351,16 @@ class _TradeTypeSelector extends StatelessWidget {
|
||||
child: _TypeButton(
|
||||
label: '买入',
|
||||
isSelected: tradeType == 0,
|
||||
color: AppColors.up,
|
||||
color: AppColorScheme.up,
|
||||
onTap: () => onChanged(0),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
SizedBox(width: AppSpacing.md),
|
||||
Expanded(
|
||||
child: _TypeButton(
|
||||
label: '卖出',
|
||||
isSelected: tradeType == 1,
|
||||
color: AppColors.down,
|
||||
color: AppColorScheme.down,
|
||||
onTap: () => onChanged(1),
|
||||
),
|
||||
),
|
||||
@@ -386,10 +388,10 @@ class _TypeButton extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? color : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
border: isSelected ? null : Border.all(color: color),
|
||||
),
|
||||
child: Center(
|
||||
@@ -441,7 +443,7 @@ class _TradeButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final color = isBuy ? AppColors.up : AppColors.down;
|
||||
final color = isBuy ? AppColorScheme.up : AppColorScheme.down;
|
||||
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
@@ -453,7 +455,7 @@ class _TradeButton extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(isBuy ? LucideIcons.arrowDownToLine : LucideIcons.arrowUpFromLine, size: 18, color: Colors.white),
|
||||
const SizedBox(width: 8),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
Text(
|
||||
'${isBuy ? '买入' : '卖出'} ${coinCode ?? ''}',
|
||||
style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w600),
|
||||
|
||||
Reference in New Issue
Block a user