111
This commit is contained in:
@@ -1,16 +1,18 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../core/network/api_response.dart';
|
||||
import '../core/network/dio_client.dart';
|
||||
import '../core/event/app_event_bus.dart';
|
||||
import '../data/models/account_models.dart';
|
||||
import '../data/models/order_models.dart';
|
||||
import '../data/services/asset_service.dart';
|
||||
import '../data/services/fund_service.dart';
|
||||
import '../data/services/trade_service.dart';
|
||||
|
||||
/// 資產狀態管理
|
||||
class AssetProvider extends ChangeNotifier {
|
||||
final AssetService _assetService;
|
||||
final FundService _fundService;
|
||||
final TradeService _tradeService;
|
||||
final AppEventBus _eventBus;
|
||||
|
||||
AssetOverview? _overview;
|
||||
@@ -18,6 +20,7 @@ class AssetProvider extends ChangeNotifier {
|
||||
List<AccountTrade> _tradeAccounts = [];
|
||||
List<AccountFlow> _flows = [];
|
||||
List<OrderFund> _fundOrders = [];
|
||||
List<OrderTrade> _tradeOrders = [];
|
||||
bool _isLoading = false;
|
||||
bool _isLoadingFlows = false;
|
||||
bool _isLoadingOrders = false;
|
||||
@@ -28,7 +31,10 @@ class AssetProvider extends ChangeNotifier {
|
||||
bool _fundAccountLoaded = false;
|
||||
bool _tradeAccountLoaded = false;
|
||||
|
||||
AssetProvider(this._assetService, this._fundService, this._eventBus);
|
||||
// 去重:防止并发调用同一 API
|
||||
Completer<void>? _refreshAllCompleter;
|
||||
|
||||
AssetProvider(this._assetService, this._fundService, this._tradeService, this._eventBus);
|
||||
|
||||
// Getters
|
||||
AssetOverview? get overview => _overview;
|
||||
@@ -37,6 +43,7 @@ class AssetProvider extends ChangeNotifier {
|
||||
List<AccountTrade> get holdings => _tradeAccounts;
|
||||
List<AccountFlow> get flows => _flows;
|
||||
List<OrderFund> get fundOrders => _fundOrders;
|
||||
List<OrderTrade> get tradeOrders => _tradeOrders;
|
||||
bool get isLoading => _isLoading;
|
||||
bool get isLoadingFlows => _isLoadingFlows;
|
||||
bool get isLoadingOrders => _isLoadingOrders;
|
||||
@@ -232,6 +239,22 @@ class AssetProvider extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// 加載交易記錄
|
||||
Future<void> loadTradeOrders({int? direction, int pageNum = 1, int pageSize = 20}) async {
|
||||
try {
|
||||
final response = await _tradeService.getOrders(
|
||||
direction: direction,
|
||||
pageNum: pageNum,
|
||||
pageSize: pageSize,
|
||||
);
|
||||
if (response.success && response.data != null) {
|
||||
final list = response.data!['list'] as List?;
|
||||
_tradeOrders = list?.map((e) => OrderTrade.fromJson(e as Map<String, dynamic>)).toList() ?? [];
|
||||
notifyListeners();
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
/// 取消訂單
|
||||
Future<ApiResponse<void>> cancelOrder(String orderNo) async {
|
||||
try {
|
||||
@@ -261,13 +284,24 @@ class AssetProvider extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// 刷新所有資產數據
|
||||
/// 刷新所有資產數據(带去重)
|
||||
Future<void> refreshAll({bool force = false}) async {
|
||||
await Future.wait([
|
||||
loadOverview(force: force),
|
||||
loadFundAccount(force: force),
|
||||
loadTradeAccount(force: force),
|
||||
]);
|
||||
if (_refreshAllCompleter != null && !_refreshAllCompleter!.isCompleted) {
|
||||
return _refreshAllCompleter!.future;
|
||||
}
|
||||
_refreshAllCompleter = Completer<void>();
|
||||
try {
|
||||
await Future.wait([
|
||||
loadOverview(force: force),
|
||||
loadFundAccount(force: force),
|
||||
loadTradeAccount(force: force),
|
||||
]);
|
||||
_refreshAllCompleter!.complete();
|
||||
} catch (e) {
|
||||
if (!_refreshAllCompleter!.isCompleted) _refreshAllCompleter!.completeError(e);
|
||||
} finally {
|
||||
_refreshAllCompleter = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 重置加載狀態(用於退出登錄時)
|
||||
@@ -280,6 +314,7 @@ class AssetProvider extends ChangeNotifier {
|
||||
_tradeAccounts = [];
|
||||
_flows = [];
|
||||
_fundOrders = [];
|
||||
_tradeOrders = [];
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import '../core/network/dio_client.dart';
|
||||
import '../core/storage/local_storage.dart';
|
||||
import '../data/models/user.dart';
|
||||
import '../data/services/user_service.dart';
|
||||
import '../main.dart';
|
||||
import '../ui/pages/auth/login_page.dart';
|
||||
|
||||
/// 認證狀態管理
|
||||
class AuthProvider extends ChangeNotifier {
|
||||
@@ -112,16 +114,13 @@ class AuthProvider extends ChangeNotifier {
|
||||
|
||||
/// 退出登錄
|
||||
Future<void> logout() async {
|
||||
_setLoading(true);
|
||||
|
||||
try {
|
||||
await _userService.logout();
|
||||
} catch (_) {
|
||||
// 忽略退出登錄的接口錯誤
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
_clearAuthState();
|
||||
_setLoading(false);
|
||||
notifyListeners();
|
||||
_navigateToLogin();
|
||||
}
|
||||
|
||||
void _clearAuthState() {
|
||||
@@ -135,6 +134,18 @@ class AuthProvider extends ChangeNotifier {
|
||||
void forceLogout() {
|
||||
_clearAuthState();
|
||||
notifyListeners();
|
||||
_navigateToLogin();
|
||||
}
|
||||
|
||||
/// 使用全局導航 Key 跳轉到登錄頁並清空路由棧
|
||||
void _navigateToLogin() {
|
||||
final nav = navigatorKey.currentState;
|
||||
if (nav != null) {
|
||||
nav.pushAndRemoveUntil(
|
||||
MaterialPageRoute(builder: (_) => LoginPage()),
|
||||
(route) => false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 刷新用戶信息
|
||||
|
||||
@@ -7,6 +7,8 @@ class MarketProvider extends ChangeNotifier {
|
||||
final MarketService _marketService;
|
||||
|
||||
List<Coin> _allCoins = [];
|
||||
List<Coin> _platformCoins = [];
|
||||
List<Coin> _nonPlatformCoins = [];
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
bool _coinsLoaded = false;
|
||||
@@ -18,14 +20,8 @@ class MarketProvider extends ChangeNotifier {
|
||||
bool get isLoading => _isLoading;
|
||||
String? get error => _error;
|
||||
|
||||
/// BTC 和 ETH(上半區展示)
|
||||
List<Coin> get featuredCoins =>
|
||||
_allCoins.where((c) => c.code == 'BTC' || c.code == 'ETH').toList();
|
||||
|
||||
/// 排除 BTC、ETH、USDT 的代幣列表(下半區展示)
|
||||
List<Coin> get otherCoins => _allCoins
|
||||
.where((c) => !{'BTC', 'ETH', 'USDT'}.contains(c.code))
|
||||
.toList();
|
||||
List<Coin> get platformCoins => _platformCoins;
|
||||
List<Coin> get nonPlatformCoins => _nonPlatformCoins;
|
||||
|
||||
/// 加載幣種列表
|
||||
Future<void> loadCoins({bool force = false}) async {
|
||||
@@ -33,21 +29,37 @@ class MarketProvider extends ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
final isFirstLoad = !_coinsLoaded || _allCoins.isEmpty;
|
||||
if (isFirstLoad) {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
try {
|
||||
final response = await _marketService.getCoinList();
|
||||
|
||||
if (response.success) {
|
||||
_allCoins = response.data ?? [];
|
||||
_platformCoins = _allCoins.where((c) => c.isPlatform == 1 && c.status == 1).toList();
|
||||
_nonPlatformCoins = _allCoins.where((c) => c.isPlatform != 1 && c.code != 'USDT').toList();
|
||||
_coinsLoaded = true;
|
||||
_error = null;
|
||||
} else {
|
||||
_error = response.message;
|
||||
// 非首次加载时保留旧数据,仅记录错误
|
||||
if (!isFirstLoad && _allCoins.isNotEmpty) {
|
||||
_error = null;
|
||||
} else {
|
||||
_error = response.message;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
_error = '加載失敗: $e';
|
||||
// 非首次加载且有缓存数据时,不覆盖为错误状态
|
||||
if (!isFirstLoad && _allCoins.isNotEmpty) {
|
||||
_error = null;
|
||||
} else {
|
||||
_error = '加載失敗: $e';
|
||||
}
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
|
||||
Reference in New Issue
Block a user