feat: 主页添加钱包生成状态轮询
手机号注册后跳转到主页,在主页后台轮询钱包生成状态: 功能实现: - 添加钱包生成状态枚举(unknown/creating/ready/failed) - 每5秒调用 GET /user/wallet 检查钱包状态 - 钱包就绪或失败后停止轮询 UI 显示: - 钱包创建中:显示"创建账号审核中..."加载动画 - 钱包创建失败:显示错误信息和"重试"按钮 - 钱包已就绪:显示正常序列号 重试机制: - 用户可点击"重试"按钮手动触发钱包生成 - 调用 POST /user/wallet/retry API - 重新开始轮询直到成功 流程: 手机号注册 → 设置密码 → 跳转主页 → 后台轮询钱包状态 → 完成 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
636a06c241
commit
08ec49322d
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
|
@ -10,6 +11,14 @@ enum MonitorStatus {
|
|||
active, // 监控中
|
||||
}
|
||||
|
||||
/// 钱包生成状态枚举
|
||||
enum WalletCreationStatus {
|
||||
unknown, // 未知
|
||||
creating, // 创建中(显示"创建账号审核中...")
|
||||
ready, // 已就绪
|
||||
failed, // 失败
|
||||
}
|
||||
|
||||
/// 监控页面 - 显示监控状态和控制
|
||||
/// 展示用户序列号、社区信息,未来将接入实时监控视频流
|
||||
class MiningPage extends ConsumerStatefulWidget {
|
||||
|
|
@ -34,6 +43,11 @@ class _MiningPageState extends ConsumerState<MiningPage> {
|
|||
String _province = '--';
|
||||
String _city = '--';
|
||||
|
||||
// 钱包生成状态
|
||||
WalletCreationStatus _walletStatus = WalletCreationStatus.unknown;
|
||||
String? _walletError;
|
||||
Timer? _walletPollingTimer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
|
@ -41,6 +55,14 @@ class _MiningPageState extends ConsumerState<MiningPage> {
|
|||
_checkLocalAvatarSync();
|
||||
_loadUserData();
|
||||
_loadAuthorizationData();
|
||||
// 开始轮询钱包状态
|
||||
_startWalletPolling();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_walletPollingTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// 同步检查本地头像文件(在 build 之前快速获取)
|
||||
|
|
@ -124,6 +146,79 @@ class _MiningPageState extends ConsumerState<MiningPage> {
|
|||
}
|
||||
}
|
||||
|
||||
/// 开始轮询钱包生成状态
|
||||
void _startWalletPolling() {
|
||||
debugPrint('[MiningPage] 开始轮询钱包生成状态...');
|
||||
|
||||
// 立即检查一次
|
||||
_checkWalletStatus();
|
||||
|
||||
// 每5秒检查一次
|
||||
_walletPollingTimer = Timer.periodic(const Duration(seconds: 5), (_) {
|
||||
_checkWalletStatus();
|
||||
});
|
||||
}
|
||||
|
||||
/// 检查钱包生成状态
|
||||
Future<void> _checkWalletStatus() async {
|
||||
try {
|
||||
final accountService = ref.read(accountServiceProvider);
|
||||
final walletInfo = await accountService.getWalletInfo(_serialNumber);
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
setState(() {
|
||||
if (walletInfo.isReady) {
|
||||
_walletStatus = WalletCreationStatus.ready;
|
||||
_walletError = null;
|
||||
// 钱包已就绪,停止轮询
|
||||
_walletPollingTimer?.cancel();
|
||||
debugPrint('[MiningPage] 钱包已就绪,停止轮询');
|
||||
} else if (walletInfo.isFailed) {
|
||||
_walletStatus = WalletCreationStatus.failed;
|
||||
_walletError = '账号创建失败';
|
||||
_walletPollingTimer?.cancel();
|
||||
debugPrint('[MiningPage] 钱包创建失败');
|
||||
} else {
|
||||
_walletStatus = WalletCreationStatus.creating;
|
||||
_walletError = null;
|
||||
debugPrint('[MiningPage] 钱包创建中...');
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
debugPrint('[MiningPage] 检查钱包状态失败: $e');
|
||||
// 不改变状态,继续轮询
|
||||
}
|
||||
}
|
||||
|
||||
/// 手动重试钱包生成
|
||||
Future<void> _retryWalletGeneration() async {
|
||||
try {
|
||||
debugPrint('[MiningPage] 手动重试钱包生成...');
|
||||
final accountService = ref.read(accountServiceProvider);
|
||||
await accountService.retryWalletGeneration();
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
// 重置状态并重新开始轮询
|
||||
setState(() {
|
||||
_walletStatus = WalletCreationStatus.creating;
|
||||
_walletError = null;
|
||||
});
|
||||
|
||||
// 重新开始轮询
|
||||
_walletPollingTimer?.cancel();
|
||||
_startWalletPolling();
|
||||
} catch (e) {
|
||||
debugPrint('[MiningPage] 重试钱包生成失败: $e');
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_walletError = '重试失败: $e';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 显示帮助信息
|
||||
void _showHelpInfo() {
|
||||
showDialog(
|
||||
|
|
@ -314,17 +409,79 @@ class _MiningPageState extends ConsumerState<MiningPage> {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'序列号$_serialNumber',
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: FontWeight.w700,
|
||||
height: 1.25,
|
||||
letterSpacing: -0.3,
|
||||
color: Color(0xFF5D4037),
|
||||
// 根据钱包状态显示不同内容
|
||||
if (_walletStatus == WalletCreationStatus.creating)
|
||||
Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFF8B5A2B)),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'创建账号审核中...',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF8B5A2B),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
else if (_walletStatus == WalletCreationStatus.failed)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
_walletError ?? '账号创建失败',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
GestureDetector(
|
||||
onTap: _retryWalletGeneration,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF8B5A2B),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: const Text(
|
||||
'重试',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
else
|
||||
Text(
|
||||
'序列号$_serialNumber',
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontFamily: 'Inter',
|
||||
fontWeight: FontWeight.w700,
|
||||
height: 1.25,
|
||||
letterSpacing: -0.3,
|
||||
color: Color(0xFF5D4037),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'社区: $_community${locationText.isNotEmpty ? ' / $locationText' : ''}',
|
||||
|
|
|
|||
Loading…
Reference in New Issue