feat(mobile-app): 为3个主导航页面添加下拉刷新功能
- TradingPage (兑换): 添加 RefreshIndicator,刷新时重新加载钱包和收益数据 - RankingPage (龙虎榜): 添加 RefreshIndicator,刷新时 invalidate leaderboardStatusProvider - 列表视图和待开启状态视图均支持下拉刷新 - MiningPage (监控): 使用 LayoutBuilder + IntrinsicHeight 模式实现 - 刷新时并行加载用户数据、授权数据和钱包状态 注:ProfilePage 已有完整的下拉刷新实现,无需修改 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
a1aba14ccf
commit
5bacd21840
|
|
@ -224,6 +224,16 @@ class _MiningPageState extends ConsumerState<MiningPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 下拉刷新
|
||||||
|
Future<void> _onRefresh() async {
|
||||||
|
debugPrint('[MiningPage] 下拉刷新');
|
||||||
|
await Future.wait([
|
||||||
|
_loadUserData(),
|
||||||
|
_loadAuthorizationData(),
|
||||||
|
_checkWalletStatus(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/// 开启监控
|
/// 开启监控
|
||||||
void _startMonitor() {
|
void _startMonitor() {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
@ -268,18 +278,35 @@ class _MiningPageState extends ConsumerState<MiningPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: Column(
|
child: RefreshIndicator(
|
||||||
children: [
|
onRefresh: _onRefresh,
|
||||||
// 顶部标题栏
|
color: const Color(0xFFD4AF37),
|
||||||
_buildAppBar(),
|
backgroundColor: Colors.white,
|
||||||
// 用户信息区域
|
child: LayoutBuilder(
|
||||||
_buildUserInfo(),
|
builder: (context, constraints) {
|
||||||
const SizedBox(height: 24),
|
return SingleChildScrollView(
|
||||||
// 挖矿状态区域
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
Expanded(
|
child: ConstrainedBox(
|
||||||
child: _buildMiningStatusArea(),
|
constraints: BoxConstraints(minHeight: constraints.maxHeight),
|
||||||
),
|
child: IntrinsicHeight(
|
||||||
],
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// 顶部标题栏
|
||||||
|
_buildAppBar(),
|
||||||
|
// 用户信息区域
|
||||||
|
_buildUserInfo(),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
// 挖矿状态区域
|
||||||
|
Expanded(
|
||||||
|
child: _buildMiningStatusArea(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,13 @@ class _RankingPageState extends ConsumerState<RankingPage> {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// 下拉刷新
|
||||||
|
Future<void> _onRefresh() async {
|
||||||
|
debugPrint('[RankingPage] 下拉刷新');
|
||||||
|
ref.invalidate(leaderboardStatusProvider);
|
||||||
|
// TODO: 未来对接真实排行榜数据时,在此处 invalidate 排行榜数据 Provider
|
||||||
|
}
|
||||||
|
|
||||||
/// 切换排行榜类型
|
/// 切换排行榜类型
|
||||||
void _selectRankingType(RankingType type) {
|
void _selectRankingType(RankingType type) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
@ -198,46 +205,61 @@ class _RankingPageState extends ConsumerState<RankingPage> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Center(
|
return RefreshIndicator(
|
||||||
child: Column(
|
onRefresh: _onRefresh,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
color: const Color(0xFFD4AF37),
|
||||||
children: [
|
backgroundColor: Colors.white,
|
||||||
// 图标
|
child: LayoutBuilder(
|
||||||
Container(
|
builder: (context, constraints) {
|
||||||
width: 80,
|
return SingleChildScrollView(
|
||||||
height: 80,
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
decoration: BoxDecoration(
|
child: ConstrainedBox(
|
||||||
color: const Color(0x1A8B5A2B),
|
constraints: BoxConstraints(minHeight: constraints.maxHeight),
|
||||||
borderRadius: BorderRadius.circular(40),
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
// 图标
|
||||||
|
Container(
|
||||||
|
width: 80,
|
||||||
|
height: 80,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0x1A8B5A2B),
|
||||||
|
borderRadius: BorderRadius.circular(40),
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.hourglass_empty,
|
||||||
|
size: 40,
|
||||||
|
color: Color(0xFF8B5A2B),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
// 标题
|
||||||
|
Text(
|
||||||
|
'$boardName待开启',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontFamily: 'Inter',
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Color(0xFF5D4037),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
// 描述
|
||||||
|
const Text(
|
||||||
|
'该榜单暂未开启,请稍后再来',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontFamily: 'Inter',
|
||||||
|
color: Color(0xFF8B5A2B),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
);
|
||||||
Icons.hourglass_empty,
|
},
|
||||||
size: 40,
|
|
||||||
color: Color(0xFF8B5A2B),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
// 标题
|
|
||||||
Text(
|
|
||||||
'$boardName待开启',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
fontFamily: 'Inter',
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: Color(0xFF5D4037),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
// 描述
|
|
||||||
const Text(
|
|
||||||
'该榜单暂未开启,请稍后再来',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontFamily: 'Inter',
|
|
||||||
color: Color(0xFF8B5A2B),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -461,15 +483,21 @@ class _RankingPageState extends ConsumerState<RankingPage> {
|
||||||
|
|
||||||
/// 构建排行榜列表
|
/// 构建排行榜列表
|
||||||
Widget _buildRankingList() {
|
Widget _buildRankingList() {
|
||||||
return ListView.builder(
|
return RefreshIndicator(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
onRefresh: _onRefresh,
|
||||||
itemCount: _mockRankingData.length,
|
color: const Color(0xFFD4AF37),
|
||||||
itemBuilder: (context, index) {
|
backgroundColor: Colors.white,
|
||||||
return Padding(
|
child: ListView.builder(
|
||||||
padding: const EdgeInsets.only(bottom: 4),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
child: _buildRankingItem(_mockRankingData[index]),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
);
|
itemCount: _mockRankingData.length,
|
||||||
},
|
itemBuilder: (context, index) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
|
child: _buildRankingItem(_mockRankingData[index]),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,12 @@ class _TradingPageState extends ConsumerState<TradingPage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 下拉刷新
|
||||||
|
Future<void> _onRefresh() async {
|
||||||
|
debugPrint('[TradingPage] 下拉刷新');
|
||||||
|
await _loadWalletData();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|
@ -236,8 +242,13 @@ class _TradingPageState extends ConsumerState<TradingPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: SingleChildScrollView(
|
child: RefreshIndicator(
|
||||||
child: Column(
|
onRefresh: _onRefresh,
|
||||||
|
color: const Color(0xFFD4AF37),
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// 顶部标题栏
|
// 顶部标题栏
|
||||||
_buildAppBar(),
|
_buildAppBar(),
|
||||||
|
|
@ -273,6 +284,7 @@ class _TradingPageState extends ConsumerState<TradingPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue