This commit is contained in:
sion
2026-04-07 01:05:05 +08:00
parent edad10ff06
commit 5ca1274607
83 changed files with 1561 additions and 1241 deletions

View File

@@ -15,14 +15,14 @@ import 'components/trade_form_card.dart';
import 'components/trade_button.dart';
import 'components/confirm_dialog.dart';
/// 交易
/// 交易
///
/// 设计稿 Trade 面,布局结构
/// - 币种选择器卡片Coin Selector Card
/// - 格卡片Price Card号价格 + 跌幅徽章 + 副标题
/// - 入/出切Buy/Sell Toggle
/// - 交易表卡片Trade Form Card额输入 + 快捷比例 + 计算数
/// - CTA 入/出按Buy/Sell Button
/// 設計稿 Trade 面,佈局結構
/// - 幣種選擇器卡片Coin Selector Card
/// - 格卡片Price Card號價格 + 跌幅徽章 + 副標題
/// - 入/出切Buy/Sell Toggle
/// - 交易表卡片Trade Form Card額輸入 + 快捷比例 + 計算數
/// - CTA 入/出按Buy/Sell Button
class TradePage extends StatefulWidget {
final String? initialCoinCode;
@@ -34,7 +34,7 @@ class TradePage extends StatefulWidget {
class _TradePageState extends State<TradePage>
with AutomaticKeepAliveClientMixin {
int _tradeType = 0; // 0=入, 1=
int _tradeType = 0; // 0=入, 1=
Coin? _selectedCoin;
final _amountController = TextEditingController();
bool _isSubmitting = false;
@@ -71,14 +71,14 @@ class _TradePageState extends State<TradePage>
super.dispose();
}
/// 取交易账户中 USDT 可用余额
/// 取交易賬戶中 USDT 可用餘額
String get _availableUsdt {
final holdings = context.read<AssetProvider>().holdings;
final usdt = holdings.where((h) => h.coinCode == 'USDT').firstOrNull;
return usdt?.quantity ?? '0';
}
/// 取交易账户中当前币种的持仓数
/// 取交易賬戶中當前幣種的持倉數
String get _availableCoinQty {
if (_selectedCoin == null) return '0';
final holdings = context.read<AssetProvider>().holdings;
@@ -88,7 +88,7 @@ class _TradePageState extends State<TradePage>
return pos?.quantity ?? '0';
}
/// 算可入/出的最大 USDT 金
/// 算可入/出的最大 USDT 金
String get _maxAmount {
if (_selectedCoin == null) return '0';
final price = _selectedCoin!.price;
@@ -102,7 +102,7 @@ class _TradePageState extends State<TradePage>
}
}
/// 计算数
/// 計算數
String get _calculatedQuantity {
final amount = double.tryParse(_amountController.text) ?? 0;
final price = _selectedCoin?.price ?? 0;
@@ -121,11 +121,11 @@ class _TradePageState extends State<TradePage>
return SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(
AppSpacing.md, AppSpacing.md, AppSpacing.md, AppSpacing.xl + AppSpacing.sm, // 添加顶部间
AppSpacing.md, AppSpacing.md, AppSpacing.md, AppSpacing.xl + AppSpacing.sm, // 添加頂部間
),
child: Column(
children: [
// 币种选择器卡片
// 幣種選擇器卡片
CoinSelector(
selectedCoin: _selectedCoin,
coins: market.allCoins
@@ -143,16 +143,16 @@ class _TradePageState extends State<TradePage>
),
const SizedBox(height: AppSpacing.md),
// 格卡片
// 格卡片
if (_selectedCoin != null)
PriceCard(coin: _selectedCoin!)
else
PlaceholderCard(
message: '请先选择交易币种',
message: '請先選擇交易幣種',
),
const SizedBox(height: AppSpacing.md),
// 交易表卡片(内含买入/出切 + 表
// 交易表卡片(內含買入/出切 + 表
TradeFormCard(
tradeType: _tradeType,
selectedCoin: _selectedCoin,
@@ -170,7 +170,7 @@ class _TradePageState extends State<TradePage>
),
const SizedBox(height: AppSpacing.md),
// CTA 入/出按
// CTA 入/出按
SizedBox(
width: double.infinity,
height: 48,
@@ -195,7 +195,7 @@ class _TradePageState extends State<TradePage>
if (_selectedCoin == null) return false;
final amount = double.tryParse(_amountController.text) ?? 0;
if (amount <= 0) return false;
// 买入时校验不超可用USDT
// 買入時校驗不超可用USDT
if (_tradeType == 0) {
final available = double.tryParse(_availableUsdt) ?? 0;
if (amount > available) return false;
@@ -243,16 +243,16 @@ class _TradePageState extends State<TradePage>
if (response.success) {
_amountController.clear();
// 刷新资产数据
// 刷新資產數據
context.read<AssetProvider>().refreshAll(force: true);
_showResultDialog(true, '${isBuy ? '' : ''}成功',
_showResultDialog(true, '${isBuy ? '' : ''}成功',
'$quantity $coinCode @ $price USDT');
} else {
_showResultDialog(false, '交易失', response.message ?? '请稍后重试');
_showResultDialog(false, '交易失', response.message ?? '請稍後重試');
}
} catch (e) {
if (mounted) {
_showResultDialog(false, '交易失', e.toString());
_showResultDialog(false, '交易失', e.toString());
}
} finally {
if (mounted) setState(() => _isSubmitting = false);
@@ -279,7 +279,7 @@ class _TradePageState extends State<TradePage>
description: Text(message),
actions: [
ShadButton(
child: const Text(''),
child: const Text(''),
onPressed: () => Navigator.of(ctx).pop(),
),
],