fix(frontend): 修复资产页面1秒实时刷新问题
- 使用 mining-service 的 perSecondEarning 替代 assetGrowthPerSecond - 添加 _timerStarted 标志防止定时器重复启动 - 修复页面进入时定时器可能未启动的问题 - 下拉刷新时同步刷新 shareAccountProvider - 正确显示每秒增长值 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5c633b9979
commit
d8dd38e91b
|
|
@ -7,6 +7,7 @@ import '../../../core/utils/format_utils.dart';
|
||||||
import '../../../domain/entities/asset_display.dart';
|
import '../../../domain/entities/asset_display.dart';
|
||||||
import '../../providers/user_providers.dart';
|
import '../../providers/user_providers.dart';
|
||||||
import '../../providers/asset_providers.dart';
|
import '../../providers/asset_providers.dart';
|
||||||
|
import '../../providers/mining_providers.dart';
|
||||||
import '../../widgets/shimmer_loading.dart';
|
import '../../widgets/shimmer_loading.dart';
|
||||||
|
|
||||||
class AssetPage extends ConsumerStatefulWidget {
|
class AssetPage extends ConsumerStatefulWidget {
|
||||||
|
|
@ -36,6 +37,7 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
double _initialShareBalance = 0;
|
double _initialShareBalance = 0;
|
||||||
double _growthPerSecond = 0;
|
double _growthPerSecond = 0;
|
||||||
String? _lastAccountSequence;
|
String? _lastAccountSequence;
|
||||||
|
bool _timerStarted = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|
@ -43,13 +45,18 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 启动定时器
|
/// 启动定时器(使用外部传入的每秒增长值)
|
||||||
void _startTimer(AssetDisplay asset) {
|
void _startTimerWithGrowth(AssetDisplay asset, String perSecondEarning) {
|
||||||
|
// 防止重复启动
|
||||||
|
if (_timerStarted && _refreshTimer != null) return;
|
||||||
|
|
||||||
_refreshTimer?.cancel();
|
_refreshTimer?.cancel();
|
||||||
_elapsedSeconds = 0;
|
_elapsedSeconds = 0;
|
||||||
_initialDisplayValue = double.tryParse(asset.displayAssetValue) ?? 0;
|
_initialDisplayValue = double.tryParse(asset.displayAssetValue) ?? 0;
|
||||||
_initialShareBalance = double.tryParse(asset.shareBalance) ?? 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) {
|
_refreshTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
|
@ -63,7 +70,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
/// 重置定时器(刷新时调用)
|
/// 重置定时器(刷新时调用)
|
||||||
void _resetTimer() {
|
void _resetTimer() {
|
||||||
_refreshTimer?.cancel();
|
_refreshTimer?.cancel();
|
||||||
|
_refreshTimer = null;
|
||||||
_elapsedSeconds = 0;
|
_elapsedSeconds = 0;
|
||||||
|
_timerStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 计算当前实时资产显示值
|
/// 计算当前实时资产显示值
|
||||||
|
|
@ -84,18 +93,37 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
final accountSequence = user.accountSequence ?? '';
|
final accountSequence = user.accountSequence ?? '';
|
||||||
// 使用 public API,不依赖 JWT token
|
// 使用 public API,不依赖 JWT token
|
||||||
final assetAsync = ref.watch(accountAssetProvider(accountSequence));
|
final assetAsync = ref.watch(accountAssetProvider(accountSequence));
|
||||||
|
// 从 mining-service 获取每秒收益
|
||||||
|
final shareAccountAsync = ref.watch(shareAccountProvider(accountSequence));
|
||||||
|
|
||||||
// 提取数据和加载状态
|
// 提取数据和加载状态
|
||||||
final isLoading = assetAsync.isLoading || accountSequence.isEmpty;
|
final isLoading = assetAsync.isLoading || accountSequence.isEmpty;
|
||||||
final asset = assetAsync.valueOrNull;
|
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)) {
|
if (asset != null && hasValidGrowth) {
|
||||||
_lastAccountSequence = accountSequence;
|
// 账户切换或首次加载时重置并启动定时器
|
||||||
_lastAsset = asset;
|
if (_lastAccountSequence != accountSequence) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
_lastAccountSequence = accountSequence;
|
||||||
_startTimer(asset);
|
_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) {
|
} else if (asset != null) {
|
||||||
_lastAsset = asset;
|
_lastAsset = asset;
|
||||||
}
|
}
|
||||||
|
|
@ -111,6 +139,7 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
_resetTimer();
|
_resetTimer();
|
||||||
_lastAsset = null;
|
_lastAsset = null;
|
||||||
ref.invalidate(accountAssetProvider(accountSequence));
|
ref.invalidate(accountAssetProvider(accountSequence));
|
||||||
|
ref.invalidate(shareAccountProvider(accountSequence));
|
||||||
},
|
},
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
|
@ -127,13 +156,13 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
// 总资产卡片 - 始终显示,数字部分闪烁,实时刷新
|
// 总资产卡片 - 始终显示,数字部分闪烁,实时刷新
|
||||||
_buildTotalAssetCard(asset, isLoading, _currentDisplayValue),
|
_buildTotalAssetCard(asset, isLoading, _currentDisplayValue, perSecondEarning),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
// 快捷操作按钮
|
// 快捷操作按钮
|
||||||
_buildQuickActions(context),
|
_buildQuickActions(context),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
// 资产列表 - 始终显示,数字部分闪烁,实时刷新
|
// 资产列表 - 始终显示,数字部分闪烁,实时刷新
|
||||||
_buildAssetList(asset, isLoading, _currentShareBalance),
|
_buildAssetList(asset, isLoading, _currentShareBalance, perSecondEarning),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
// 交易统计
|
// 交易统计
|
||||||
_buildEarningsCard(asset, isLoading),
|
_buildEarningsCard(asset, isLoading),
|
||||||
|
|
@ -172,11 +201,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTotalAssetCard(AssetDisplay? asset, bool isLoading, double currentDisplayValue) {
|
Widget _buildTotalAssetCard(AssetDisplay? asset, bool isLoading, double currentDisplayValue, String perSecondEarning) {
|
||||||
// 计算每秒增长
|
// 使用传入的每秒增长值(来自 mining-service)
|
||||||
final growthPerSecond = asset != null
|
final growthPerSecond = double.tryParse(perSecondEarning) ?? 0.0;
|
||||||
? AssetValueCalculator.calculateGrowthPerSecond(asset.assetGrowthPerSecond)
|
|
||||||
: 0.0;
|
|
||||||
|
|
||||||
// 使用实时计算的资产值(如果有)
|
// 使用实时计算的资产值(如果有)
|
||||||
final displayValue = asset != null && currentDisplayValue > 0
|
final displayValue = asset != null && currentDisplayValue > 0
|
||||||
|
|
@ -372,7 +399,7 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAssetList(AssetDisplay? asset, bool isLoading, double currentShareBalance) {
|
Widget _buildAssetList(AssetDisplay? asset, bool isLoading, double currentShareBalance, String perSecondEarning) {
|
||||||
// 使用实时积分股余额
|
// 使用实时积分股余额
|
||||||
final shareBalance = asset != null && currentShareBalance > 0
|
final shareBalance = asset != null && currentShareBalance > 0
|
||||||
? currentShareBalance
|
? currentShareBalance
|
||||||
|
|
@ -395,7 +422,7 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||||
? '¥${formatAmount((shareBalance * currentPrice).toString())}'
|
? '¥${formatAmount((shareBalance * currentPrice).toString())}'
|
||||||
: null,
|
: null,
|
||||||
tag: asset != null ? '含倍数资产: ${formatCompact(multipliedAsset.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),
|
const SizedBox(height: 16),
|
||||||
// 积分值(现金余额)
|
// 积分值(现金余额)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue