feat(mobile): integrate wallet-service API for profile page rewards
- Add WalletService to fetch wallet/rewards data from backend - Replace hardcoded earnings data with real API calls - Add loading/error states for earnings section - Implement claim rewards functionality with API - Add comprehensive debug logging for troubleshooting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
62270ed202
commit
8335187436
|
|
@ -6,6 +6,7 @@ import '../services/account_service.dart';
|
||||||
import '../services/referral_service.dart';
|
import '../services/referral_service.dart';
|
||||||
import '../services/authorization_service.dart';
|
import '../services/authorization_service.dart';
|
||||||
import '../services/deposit_service.dart';
|
import '../services/deposit_service.dart';
|
||||||
|
import '../services/wallet_service.dart';
|
||||||
|
|
||||||
// Storage Providers
|
// Storage Providers
|
||||||
final secureStorageProvider = Provider<SecureStorage>((ref) {
|
final secureStorageProvider = Provider<SecureStorage>((ref) {
|
||||||
|
|
@ -51,6 +52,12 @@ final depositServiceProvider = Provider<DepositService>((ref) {
|
||||||
return DepositService(apiClient: apiClient, secureStorage: secureStorage);
|
return DepositService(apiClient: apiClient, secureStorage: secureStorage);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wallet Service Provider
|
||||||
|
final walletServiceProvider = Provider<WalletService>((ref) {
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
return WalletService(apiClient: apiClient);
|
||||||
|
});
|
||||||
|
|
||||||
// Override provider with initialized instance
|
// Override provider with initialized instance
|
||||||
ProviderContainer createProviderContainer(LocalStorage localStorage) {
|
ProviderContainer createProviderContainer(LocalStorage localStorage) {
|
||||||
return ProviderContainer(
|
return ProviderContainer(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,276 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import '../network/api_client.dart';
|
||||||
|
|
||||||
|
/// 余额信息
|
||||||
|
class BalanceInfo {
|
||||||
|
final double available;
|
||||||
|
final double frozen;
|
||||||
|
|
||||||
|
BalanceInfo({
|
||||||
|
required this.available,
|
||||||
|
required this.frozen,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory BalanceInfo.fromJson(Map<String, dynamic> json) {
|
||||||
|
return BalanceInfo(
|
||||||
|
available: (json['available'] ?? 0).toDouble(),
|
||||||
|
frozen: (json['frozen'] ?? 0).toDouble(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 各币种余额
|
||||||
|
class BalancesInfo {
|
||||||
|
final BalanceInfo usdt;
|
||||||
|
final BalanceInfo dst;
|
||||||
|
final BalanceInfo bnb;
|
||||||
|
final BalanceInfo og;
|
||||||
|
final BalanceInfo rwad;
|
||||||
|
|
||||||
|
BalancesInfo({
|
||||||
|
required this.usdt,
|
||||||
|
required this.dst,
|
||||||
|
required this.bnb,
|
||||||
|
required this.og,
|
||||||
|
required this.rwad,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory BalancesInfo.fromJson(Map<String, dynamic> json) {
|
||||||
|
return BalancesInfo(
|
||||||
|
usdt: BalanceInfo.fromJson(json['usdt'] ?? {}),
|
||||||
|
dst: BalanceInfo.fromJson(json['dst'] ?? {}),
|
||||||
|
bnb: BalanceInfo.fromJson(json['bnb'] ?? {}),
|
||||||
|
og: BalanceInfo.fromJson(json['og'] ?? {}),
|
||||||
|
rwad: BalanceInfo.fromJson(json['rwad'] ?? {}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 奖励信息
|
||||||
|
class RewardsInfo {
|
||||||
|
final double pendingUsdt;
|
||||||
|
final double pendingHashpower;
|
||||||
|
final DateTime? pendingExpireAt;
|
||||||
|
final double settleableUsdt;
|
||||||
|
final double settleableHashpower;
|
||||||
|
final double settledTotalUsdt;
|
||||||
|
final double settledTotalHashpower;
|
||||||
|
final double expiredTotalUsdt;
|
||||||
|
final double expiredTotalHashpower;
|
||||||
|
|
||||||
|
RewardsInfo({
|
||||||
|
required this.pendingUsdt,
|
||||||
|
required this.pendingHashpower,
|
||||||
|
this.pendingExpireAt,
|
||||||
|
required this.settleableUsdt,
|
||||||
|
required this.settleableHashpower,
|
||||||
|
required this.settledTotalUsdt,
|
||||||
|
required this.settledTotalHashpower,
|
||||||
|
required this.expiredTotalUsdt,
|
||||||
|
required this.expiredTotalHashpower,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory RewardsInfo.fromJson(Map<String, dynamic> json) {
|
||||||
|
return RewardsInfo(
|
||||||
|
pendingUsdt: (json['pendingUsdt'] ?? 0).toDouble(),
|
||||||
|
pendingHashpower: (json['pendingHashpower'] ?? 0).toDouble(),
|
||||||
|
pendingExpireAt: json['pendingExpireAt'] != null
|
||||||
|
? DateTime.tryParse(json['pendingExpireAt'])
|
||||||
|
: null,
|
||||||
|
settleableUsdt: (json['settleableUsdt'] ?? 0).toDouble(),
|
||||||
|
settleableHashpower: (json['settleableHashpower'] ?? 0).toDouble(),
|
||||||
|
settledTotalUsdt: (json['settledTotalUsdt'] ?? 0).toDouble(),
|
||||||
|
settledTotalHashpower: (json['settledTotalHashpower'] ?? 0).toDouble(),
|
||||||
|
expiredTotalUsdt: (json['expiredTotalUsdt'] ?? 0).toDouble(),
|
||||||
|
expiredTotalHashpower: (json['expiredTotalHashpower'] ?? 0).toDouble(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 计算待领取剩余时间(秒)
|
||||||
|
int get pendingRemainingSeconds {
|
||||||
|
if (pendingExpireAt == null) return 0;
|
||||||
|
final remaining = pendingExpireAt!.difference(DateTime.now()).inSeconds;
|
||||||
|
return remaining > 0 ? remaining : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 钱包响应
|
||||||
|
class WalletResponse {
|
||||||
|
final String walletId;
|
||||||
|
final String userId;
|
||||||
|
final BalancesInfo balances;
|
||||||
|
final double hashpower;
|
||||||
|
final RewardsInfo rewards;
|
||||||
|
final String status;
|
||||||
|
|
||||||
|
WalletResponse({
|
||||||
|
required this.walletId,
|
||||||
|
required this.userId,
|
||||||
|
required this.balances,
|
||||||
|
required this.hashpower,
|
||||||
|
required this.rewards,
|
||||||
|
required this.status,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory WalletResponse.fromJson(Map<String, dynamic> json) {
|
||||||
|
return WalletResponse(
|
||||||
|
walletId: json['walletId'] ?? '',
|
||||||
|
userId: json['userId'] ?? '',
|
||||||
|
balances: BalancesInfo.fromJson(json['balances'] ?? {}),
|
||||||
|
hashpower: (json['hashpower'] ?? 0).toDouble(),
|
||||||
|
rewards: RewardsInfo.fromJson(json['rewards'] ?? {}),
|
||||||
|
status: json['status'] ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 领取奖励响应
|
||||||
|
class ClaimRewardsResponse {
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
ClaimRewardsResponse({required this.message});
|
||||||
|
|
||||||
|
factory ClaimRewardsResponse.fromJson(Map<String, dynamic> json) {
|
||||||
|
return ClaimRewardsResponse(
|
||||||
|
message: json['message'] ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 钱包服务
|
||||||
|
///
|
||||||
|
/// 提供钱包余额查询、奖励领取等功能
|
||||||
|
/// 调用 wallet-service 的 API
|
||||||
|
class WalletService {
|
||||||
|
final ApiClient _apiClient;
|
||||||
|
|
||||||
|
WalletService({required ApiClient apiClient}) : _apiClient = apiClient;
|
||||||
|
|
||||||
|
/// 获取我的钱包信息
|
||||||
|
///
|
||||||
|
/// 调用 GET /wallet/my-wallet (wallet-service)
|
||||||
|
Future<WalletResponse> getMyWallet() async {
|
||||||
|
try {
|
||||||
|
debugPrint('[WalletService] ========== 获取钱包信息 ==========');
|
||||||
|
debugPrint('[WalletService] 请求: GET /wallet/my-wallet');
|
||||||
|
|
||||||
|
final response = await _apiClient.get('/wallet/my-wallet');
|
||||||
|
|
||||||
|
debugPrint('[WalletService] 响应状态码: ${response.statusCode}');
|
||||||
|
debugPrint('[WalletService] 响应数据类型: ${response.data.runtimeType}');
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = response.data as Map<String, dynamic>;
|
||||||
|
debugPrint('[WalletService] 原始响应数据: $data');
|
||||||
|
|
||||||
|
// 解析并打印详细信息
|
||||||
|
final wallet = WalletResponse.fromJson(data);
|
||||||
|
debugPrint('[WalletService] -------- 解析结果 --------');
|
||||||
|
debugPrint('[WalletService] walletId: ${wallet.walletId}');
|
||||||
|
debugPrint('[WalletService] userId: ${wallet.userId}');
|
||||||
|
debugPrint('[WalletService] status: ${wallet.status}');
|
||||||
|
debugPrint('[WalletService] hashpower: ${wallet.hashpower}');
|
||||||
|
debugPrint('[WalletService] -------- 余额信息 --------');
|
||||||
|
debugPrint('[WalletService] USDT: available=${wallet.balances.usdt.available}, frozen=${wallet.balances.usdt.frozen}');
|
||||||
|
debugPrint('[WalletService] DST: available=${wallet.balances.dst.available}, frozen=${wallet.balances.dst.frozen}');
|
||||||
|
debugPrint('[WalletService] -------- 奖励信息 --------');
|
||||||
|
debugPrint('[WalletService] pendingUsdt: ${wallet.rewards.pendingUsdt}');
|
||||||
|
debugPrint('[WalletService] pendingHashpower: ${wallet.rewards.pendingHashpower}');
|
||||||
|
debugPrint('[WalletService] pendingExpireAt: ${wallet.rewards.pendingExpireAt}');
|
||||||
|
debugPrint('[WalletService] pendingRemainingSeconds: ${wallet.rewards.pendingRemainingSeconds}');
|
||||||
|
debugPrint('[WalletService] settleableUsdt: ${wallet.rewards.settleableUsdt}');
|
||||||
|
debugPrint('[WalletService] settleableHashpower: ${wallet.rewards.settleableHashpower}');
|
||||||
|
debugPrint('[WalletService] settledTotalUsdt: ${wallet.rewards.settledTotalUsdt}');
|
||||||
|
debugPrint('[WalletService] settledTotalHashpower: ${wallet.rewards.settledTotalHashpower}');
|
||||||
|
debugPrint('[WalletService] expiredTotalUsdt: ${wallet.rewards.expiredTotalUsdt}');
|
||||||
|
debugPrint('[WalletService] expiredTotalHashpower: ${wallet.rewards.expiredTotalHashpower}');
|
||||||
|
debugPrint('[WalletService] ================================');
|
||||||
|
|
||||||
|
return wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint('[WalletService] 请求失败,状态码: ${response.statusCode}');
|
||||||
|
debugPrint('[WalletService] 响应内容: ${response.data}');
|
||||||
|
throw Exception('获取钱包信息失败: ${response.statusCode}');
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
debugPrint('[WalletService] !!!!!!!!!! 获取钱包信息异常 !!!!!!!!!!');
|
||||||
|
debugPrint('[WalletService] 错误: $e');
|
||||||
|
debugPrint('[WalletService] 堆栈: $stackTrace');
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 领取奖励
|
||||||
|
///
|
||||||
|
/// 调用 POST /wallet/claim-rewards (wallet-service)
|
||||||
|
/// 将待领取的奖励转为可结算状态
|
||||||
|
Future<ClaimRewardsResponse> claimRewards() async {
|
||||||
|
try {
|
||||||
|
debugPrint('[WalletService] ========== 领取奖励 ==========');
|
||||||
|
debugPrint('[WalletService] 请求: POST /wallet/claim-rewards');
|
||||||
|
|
||||||
|
final response = await _apiClient.post('/wallet/claim-rewards');
|
||||||
|
|
||||||
|
debugPrint('[WalletService] 响应状态码: ${response.statusCode}');
|
||||||
|
debugPrint('[WalletService] 响应数据: ${response.data}');
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = response.data as Map<String, dynamic>;
|
||||||
|
final result = ClaimRewardsResponse.fromJson(data);
|
||||||
|
debugPrint('[WalletService] 领取成功: ${result.message}');
|
||||||
|
debugPrint('[WalletService] ================================');
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint('[WalletService] 领取失败,状态码: ${response.statusCode}');
|
||||||
|
throw Exception('领取奖励失败: ${response.statusCode}');
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
debugPrint('[WalletService] !!!!!!!!!! 领取奖励异常 !!!!!!!!!!');
|
||||||
|
debugPrint('[WalletService] 错误: $e');
|
||||||
|
debugPrint('[WalletService] 堆栈: $stackTrace');
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 结算收益
|
||||||
|
///
|
||||||
|
/// 调用 POST /wallet/settle (wallet-service)
|
||||||
|
/// 将可结算的USDT兑换为指定币种
|
||||||
|
Future<String> settleRewards({
|
||||||
|
required double usdtAmount,
|
||||||
|
required String settleCurrency,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
debugPrint('[WalletService] ========== 结算收益 ==========');
|
||||||
|
debugPrint('[WalletService] 请求: POST /wallet/settle');
|
||||||
|
debugPrint('[WalletService] 参数: usdtAmount=$usdtAmount, settleCurrency=$settleCurrency');
|
||||||
|
|
||||||
|
final response = await _apiClient.post(
|
||||||
|
'/wallet/settle',
|
||||||
|
data: {
|
||||||
|
'usdtAmount': usdtAmount,
|
||||||
|
'settleCurrency': settleCurrency,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
debugPrint('[WalletService] 响应状态码: ${response.statusCode}');
|
||||||
|
debugPrint('[WalletService] 响应数据: ${response.data}');
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = response.data as Map<String, dynamic>;
|
||||||
|
final orderId = data['settlementOrderId'] ?? '';
|
||||||
|
debugPrint('[WalletService] 结算成功: orderId=$orderId');
|
||||||
|
debugPrint('[WalletService] ================================');
|
||||||
|
return orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint('[WalletService] 结算失败,状态码: ${response.statusCode}');
|
||||||
|
throw Exception('结算失败: ${response.statusCode}');
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
debugPrint('[WalletService] !!!!!!!!!! 结算收益异常 !!!!!!!!!!');
|
||||||
|
debugPrint('[WalletService] 错误: $e');
|
||||||
|
debugPrint('[WalletService] 堆栈: $stackTrace');
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -55,17 +55,19 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
final int _currentPlanting = 12;
|
final int _currentPlanting = 12;
|
||||||
final int _requiredPlanting = 50;
|
final int _requiredPlanting = 50;
|
||||||
|
|
||||||
// 收益数据
|
// 收益数据(从 wallet-service 获取)
|
||||||
final double _pendingUsdt = 320.75;
|
double _pendingUsdt = 0.0;
|
||||||
final double _pendingPower = 50.00;
|
double _pendingPower = 0.0;
|
||||||
final double _settleableUsdt = 1500.00;
|
double _settleableUsdt = 0.0;
|
||||||
final double _settledUsdt = 8500.50;
|
double _settledUsdt = 0.0;
|
||||||
final double _expiredUsdt = 250.00;
|
double _expiredUsdt = 0.0;
|
||||||
final double _expiredPower = 15.00;
|
double _expiredPower = 0.0;
|
||||||
|
bool _isLoadingWallet = true;
|
||||||
|
String? _walletError;
|
||||||
|
|
||||||
// 倒计时
|
// 倒计时
|
||||||
Timer? _timer;
|
Timer? _timer;
|
||||||
int _remainingSeconds = 66942; // 18:35:42
|
int _remainingSeconds = 0;
|
||||||
|
|
||||||
// 应用版本信息
|
// 应用版本信息
|
||||||
String _appVersion = '--';
|
String _appVersion = '--';
|
||||||
|
|
@ -78,7 +80,6 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_startCountdown();
|
|
||||||
// 先同步检查本地头像,再异步加载其他数据
|
// 先同步检查本地头像,再异步加载其他数据
|
||||||
_checkLocalAvatarSync();
|
_checkLocalAvatarSync();
|
||||||
_loadUserData();
|
_loadUserData();
|
||||||
|
|
@ -86,6 +87,8 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
// 加载推荐和授权数据
|
// 加载推荐和授权数据
|
||||||
_loadReferralData();
|
_loadReferralData();
|
||||||
_loadAuthorizationData();
|
_loadAuthorizationData();
|
||||||
|
// 加载钱包和收益数据
|
||||||
|
_loadWalletData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 加载应用信息
|
/// 加载应用信息
|
||||||
|
|
@ -298,6 +301,74 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 加载钱包和收益数据 (from wallet-service)
|
||||||
|
Future<void> _loadWalletData() async {
|
||||||
|
try {
|
||||||
|
debugPrint('[ProfilePage] ========== 加载钱包数据 ==========');
|
||||||
|
debugPrint('[ProfilePage] mounted: $mounted');
|
||||||
|
setState(() {
|
||||||
|
_isLoadingWallet = true;
|
||||||
|
_walletError = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
debugPrint('[ProfilePage] 获取 walletServiceProvider...');
|
||||||
|
final walletService = ref.read(walletServiceProvider);
|
||||||
|
debugPrint('[ProfilePage] 调用 getMyWallet()...');
|
||||||
|
final wallet = await walletService.getMyWallet();
|
||||||
|
|
||||||
|
debugPrint('[ProfilePage] -------- 钱包数据加载成功 --------');
|
||||||
|
debugPrint('[ProfilePage] 待领取 USDT: ${wallet.rewards.pendingUsdt}');
|
||||||
|
debugPrint('[ProfilePage] 待领取 算力: ${wallet.rewards.pendingHashpower}');
|
||||||
|
debugPrint('[ProfilePage] 可结算 USDT: ${wallet.rewards.settleableUsdt}');
|
||||||
|
debugPrint('[ProfilePage] 已结算 USDT: ${wallet.rewards.settledTotalUsdt}');
|
||||||
|
debugPrint('[ProfilePage] 已过期 USDT: ${wallet.rewards.expiredTotalUsdt}');
|
||||||
|
debugPrint('[ProfilePage] 已过期 算力: ${wallet.rewards.expiredTotalHashpower}');
|
||||||
|
debugPrint('[ProfilePage] 过期时间: ${wallet.rewards.pendingExpireAt}');
|
||||||
|
debugPrint('[ProfilePage] 剩余秒数: ${wallet.rewards.pendingRemainingSeconds}');
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
debugPrint('[ProfilePage] 更新 UI 状态...');
|
||||||
|
setState(() {
|
||||||
|
_pendingUsdt = wallet.rewards.pendingUsdt;
|
||||||
|
_pendingPower = wallet.rewards.pendingHashpower;
|
||||||
|
_settleableUsdt = wallet.rewards.settleableUsdt;
|
||||||
|
_settledUsdt = wallet.rewards.settledTotalUsdt;
|
||||||
|
_expiredUsdt = wallet.rewards.expiredTotalUsdt;
|
||||||
|
_expiredPower = wallet.rewards.expiredTotalHashpower;
|
||||||
|
_remainingSeconds = wallet.rewards.pendingRemainingSeconds;
|
||||||
|
_isLoadingWallet = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
debugPrint('[ProfilePage] UI 状态更新完成');
|
||||||
|
debugPrint('[ProfilePage] _pendingUsdt: $_pendingUsdt');
|
||||||
|
debugPrint('[ProfilePage] _remainingSeconds: $_remainingSeconds');
|
||||||
|
|
||||||
|
// 启动倒计时(如果有待领取收益)
|
||||||
|
if (_remainingSeconds > 0) {
|
||||||
|
debugPrint('[ProfilePage] 启动倒计时: $_remainingSeconds 秒');
|
||||||
|
_startCountdown();
|
||||||
|
} else {
|
||||||
|
debugPrint('[ProfilePage] 无需启动倒计时(剩余时间为0)');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debugPrint('[ProfilePage] 组件已卸载,跳过 UI 更新');
|
||||||
|
}
|
||||||
|
debugPrint('[ProfilePage] ================================');
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
debugPrint('[ProfilePage] !!!!!!!!!! 加载钱包数据失败 !!!!!!!!!!');
|
||||||
|
debugPrint('[ProfilePage] 错误类型: ${e.runtimeType}');
|
||||||
|
debugPrint('[ProfilePage] 错误信息: $e');
|
||||||
|
debugPrint('[ProfilePage] 堆栈跟踪:');
|
||||||
|
debugPrint('$stackTrace');
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isLoadingWallet = false;
|
||||||
|
_walletError = '加载失败,点击重试';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 后台下载并缓存头像
|
/// 后台下载并缓存头像
|
||||||
Future<void> _downloadAndCacheAvatar(String url) async {
|
Future<void> _downloadAndCacheAvatar(String url) async {
|
||||||
final accountService = ref.read(accountServiceProvider);
|
final accountService = ref.read(accountServiceProvider);
|
||||||
|
|
@ -358,27 +429,33 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
|
|
||||||
/// 领取全部收益
|
/// 领取全部收益
|
||||||
void _claimAllEarnings() {
|
void _claimAllEarnings() {
|
||||||
|
// 如果没有待领取收益,提示用户
|
||||||
|
if (_pendingUsdt <= 0 && _pendingPower <= 0) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('暂无可领取的收益'),
|
||||||
|
backgroundColor: Color(0xFF8B5A2B),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (dialogContext) => AlertDialog(
|
||||||
title: const Text('确认领取'),
|
title: const Text('确认领取'),
|
||||||
content: Text(
|
content: Text(
|
||||||
'确定领取全部收益吗?\nUSDT: ${_formatNumber(_pendingUsdt)}\n算力: ${_formatNumber(_pendingPower)}',
|
'确定领取全部收益吗?\nUSDT: ${_formatNumber(_pendingUsdt)}\n算力: ${_formatNumber(_pendingPower)}',
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(dialogContext),
|
||||||
child: const Text('取消'),
|
child: const Text('取消'),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
Navigator.pop(context);
|
Navigator.pop(dialogContext);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
await _doClaimRewards();
|
||||||
const SnackBar(
|
|
||||||
content: Text('领取成功'),
|
|
||||||
backgroundColor: Color(0xFFD4AF37),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: const Text('确认'),
|
child: const Text('确认'),
|
||||||
),
|
),
|
||||||
|
|
@ -387,6 +464,44 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 执行领取奖励
|
||||||
|
Future<void> _doClaimRewards() async {
|
||||||
|
try {
|
||||||
|
debugPrint('[ProfilePage] ========== 执行领取奖励 ==========');
|
||||||
|
debugPrint('[ProfilePage] 当前待领取: USDT=$_pendingUsdt, 算力=$_pendingPower');
|
||||||
|
|
||||||
|
final walletService = ref.read(walletServiceProvider);
|
||||||
|
debugPrint('[ProfilePage] 调用 claimRewards()...');
|
||||||
|
await walletService.claimRewards();
|
||||||
|
|
||||||
|
debugPrint('[ProfilePage] 领取成功,准备刷新数据');
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('领取成功'),
|
||||||
|
backgroundColor: Color(0xFFD4AF37),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// 刷新钱包数据
|
||||||
|
debugPrint('[ProfilePage] 刷新钱包数据...');
|
||||||
|
_loadWalletData();
|
||||||
|
}
|
||||||
|
debugPrint('[ProfilePage] ================================');
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
debugPrint('[ProfilePage] !!!!!!!!!! 领取奖励失败 !!!!!!!!!!');
|
||||||
|
debugPrint('[ProfilePage] 错误: $e');
|
||||||
|
debugPrint('[ProfilePage] 堆栈: $stackTrace');
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('领取失败: $e'),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 结算
|
/// 结算
|
||||||
void _onSettlement() {
|
void _onSettlement() {
|
||||||
context.go(RoutePaths.trading);
|
context.go(RoutePaths.trading);
|
||||||
|
|
@ -883,15 +998,68 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
width: 1,
|
width: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: _isLoadingWallet
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
? _buildLoadingState()
|
||||||
children: [
|
: _walletError != null
|
||||||
// 倒计时
|
? _buildErrorState()
|
||||||
Column(
|
: _buildEarningsContent(),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 构建加载状态
|
||||||
|
Widget _buildLoadingState() {
|
||||||
|
return const SizedBox(
|
||||||
|
height: 200,
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Color(0xFFD4AF37),
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 构建错误状态
|
||||||
|
Widget _buildErrorState() {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: _loadWalletData,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 200,
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Icon(
|
||||||
'24 小时倒计时',
|
Icons.error_outline,
|
||||||
|
color: Color(0xFFE65100),
|
||||||
|
size: 40,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
_walletError!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Color(0xFFE65100),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 构建收益内容
|
||||||
|
Widget _buildEarningsContent() {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// 倒计时
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'24 小时倒计时',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontFamily: 'Inter',
|
fontFamily: 'Inter',
|
||||||
|
|
@ -994,8 +1162,7 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 构建结算区域
|
/// 构建结算区域
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue