diff --git a/frontend/mining-app/lib/presentation/pages/asset/asset_page.dart b/frontend/mining-app/lib/presentation/pages/asset/asset_page.dart index 3c32bd95..9a5ce4ce 100644 --- a/frontend/mining-app/lib/presentation/pages/asset/asset_page.dart +++ b/frontend/mining-app/lib/presentation/pages/asset/asset_page.dart @@ -7,6 +7,7 @@ import '../../../core/utils/format_utils.dart'; import '../../../domain/entities/asset_display.dart'; import '../../providers/user_providers.dart'; import '../../providers/asset_providers.dart'; +import '../../providers/mining_providers.dart'; import '../../widgets/shimmer_loading.dart'; class AssetPage extends ConsumerStatefulWidget { @@ -36,6 +37,7 @@ class _AssetPageState extends ConsumerState { double _initialShareBalance = 0; double _growthPerSecond = 0; String? _lastAccountSequence; + bool _timerStarted = false; @override void dispose() { @@ -43,13 +45,18 @@ class _AssetPageState extends ConsumerState { super.dispose(); } - /// 启动定时器 - void _startTimer(AssetDisplay asset) { + /// 启动定时器(使用外部传入的每秒增长值) + void _startTimerWithGrowth(AssetDisplay asset, String perSecondEarning) { + // 防止重复启动 + if (_timerStarted && _refreshTimer != null) return; + _refreshTimer?.cancel(); _elapsedSeconds = 0; _initialDisplayValue = double.tryParse(asset.displayAssetValue) ?? 0; _initialShareBalance = double.tryParse(asset.shareBalance) ?? 0; - _growthPerSecond = AssetValueCalculator.calculateGrowthPerSecond(asset.assetGrowthPerSecond); + // 使用传入的每秒增长值(来自 mining-service) + _growthPerSecond = double.tryParse(perSecondEarning) ?? 0; + _timerStarted = true; _refreshTimer = Timer.periodic(const Duration(seconds: 1), (timer) { if (mounted) { @@ -63,7 +70,9 @@ class _AssetPageState extends ConsumerState { /// 重置定时器(刷新时调用) void _resetTimer() { _refreshTimer?.cancel(); + _refreshTimer = null; _elapsedSeconds = 0; + _timerStarted = false; } /// 计算当前实时资产显示值 @@ -84,18 +93,37 @@ class _AssetPageState extends ConsumerState { final accountSequence = user.accountSequence ?? ''; // 使用 public API,不依赖 JWT token final assetAsync = ref.watch(accountAssetProvider(accountSequence)); + // 从 mining-service 获取每秒收益 + final shareAccountAsync = ref.watch(shareAccountProvider(accountSequence)); // 提取数据和加载状态 final isLoading = assetAsync.isLoading || accountSequence.isEmpty; final asset = assetAsync.valueOrNull; + final shareAccount = shareAccountAsync.valueOrNull; + + // 获取每秒收益(优先使用 mining-service 的数据) + final perSecondEarning = shareAccount?.perSecondEarning ?? '0'; + final hasValidGrowth = (double.tryParse(perSecondEarning) ?? 0) > 0; // 当数据加载完成时启动定时器 - if (asset != null && (_lastAsset == null || _lastAccountSequence != accountSequence)) { - _lastAccountSequence = accountSequence; - _lastAsset = asset; - WidgetsBinding.instance.addPostFrameCallback((_) { - _startTimer(asset); - }); + if (asset != null && hasValidGrowth) { + // 账户切换或首次加载时重置并启动定时器 + if (_lastAccountSequence != accountSequence) { + _lastAccountSequence = accountSequence; + _lastAsset = asset; + _resetTimer(); + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) _startTimerWithGrowth(asset, perSecondEarning); + }); + } else if (!_timerStarted) { + // 定时器未启动时启动(例如页面刚进入) + _lastAsset = asset; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) _startTimerWithGrowth(asset, perSecondEarning); + }); + } else { + _lastAsset = asset; + } } else if (asset != null) { _lastAsset = asset; } @@ -111,6 +139,7 @@ class _AssetPageState extends ConsumerState { _resetTimer(); _lastAsset = null; ref.invalidate(accountAssetProvider(accountSequence)); + ref.invalidate(shareAccountProvider(accountSequence)); }, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), @@ -127,13 +156,13 @@ class _AssetPageState extends ConsumerState { children: [ const SizedBox(height: 8), // 总资产卡片 - 始终显示,数字部分闪烁,实时刷新 - _buildTotalAssetCard(asset, isLoading, _currentDisplayValue), + _buildTotalAssetCard(asset, isLoading, _currentDisplayValue, perSecondEarning), const SizedBox(height: 24), // 快捷操作按钮 _buildQuickActions(context), const SizedBox(height: 24), // 资产列表 - 始终显示,数字部分闪烁,实时刷新 - _buildAssetList(asset, isLoading, _currentShareBalance), + _buildAssetList(asset, isLoading, _currentShareBalance, perSecondEarning), const SizedBox(height: 24), // 交易统计 _buildEarningsCard(asset, isLoading), @@ -172,11 +201,9 @@ class _AssetPageState extends ConsumerState { ); } - Widget _buildTotalAssetCard(AssetDisplay? asset, bool isLoading, double currentDisplayValue) { - // 计算每秒增长 - final growthPerSecond = asset != null - ? AssetValueCalculator.calculateGrowthPerSecond(asset.assetGrowthPerSecond) - : 0.0; + Widget _buildTotalAssetCard(AssetDisplay? asset, bool isLoading, double currentDisplayValue, String perSecondEarning) { + // 使用传入的每秒增长值(来自 mining-service) + final growthPerSecond = double.tryParse(perSecondEarning) ?? 0.0; // 使用实时计算的资产值(如果有) final displayValue = asset != null && currentDisplayValue > 0 @@ -372,7 +399,7 @@ class _AssetPageState extends ConsumerState { ); } - Widget _buildAssetList(AssetDisplay? asset, bool isLoading, double currentShareBalance) { + Widget _buildAssetList(AssetDisplay? asset, bool isLoading, double currentShareBalance, String perSecondEarning) { // 使用实时积分股余额 final shareBalance = asset != null && currentShareBalance > 0 ? currentShareBalance @@ -395,7 +422,7 @@ class _AssetPageState extends ConsumerState { ? '¥${formatAmount((shareBalance * currentPrice).toString())}' : null, tag: asset != null ? '含倍数资产: ${formatCompact(multipliedAsset.toString())}' : null, - growthText: asset != null ? '每秒 +${formatDecimal(asset.assetGrowthPerSecond, 8)}' : null, + growthText: asset != null ? '每秒 +${formatDecimal(perSecondEarning, 8)}' : null, ), const SizedBox(height: 16), // 积分值(现金余额)