This commit is contained in:
sion
2026-04-04 21:19:29 +08:00
parent 2850629e0d
commit 37290e7846
166 changed files with 1303 additions and 220663 deletions

View File

@@ -1,3 +1,4 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
@@ -7,6 +8,7 @@ import 'package:google_fonts/google_fonts.dart';
import '../../../core/theme/app_color_scheme.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/utils/toast_utils.dart';
import '../../../core/event/app_event_bus.dart';
import '../../../data/models/account_models.dart';
import '../../../data/services/asset_service.dart';
import '../../../data/services/bonus_service.dart';
@@ -15,6 +17,7 @@ import '../../../providers/auth_provider.dart';
import '../../components/glass_panel.dart';
import '../../components/neon_glow.dart';
import '../main/main_page.dart';
import '../mine/welfare_center_page.dart';
/// 首页
class HomePage extends StatefulWidget {
@@ -26,8 +29,8 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State<HomePage>
with AutomaticKeepAliveClientMixin {
bool _bonusClaimed = false;
bool _bonusLoading = false;
int _totalClaimable = 0;
StreamSubscription<AppEvent>? _eventSub;
@override
bool get wantKeepAlive => true;
@@ -35,7 +38,26 @@ class _HomePageState extends State<HomePage>
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => _loadData());
WidgetsBinding.instance.addPostFrameCallback((_) {
_loadData();
_listenEvents();
});
}
@override
void dispose() {
_eventSub?.cancel();
super.dispose();
}
void _listenEvents() {
final eventBus = context.read<AppEventBus>();
_eventSub = eventBus.on(AppEventType.assetChanged, (_) {
if (mounted) {
context.read<AssetProvider>().loadOverview(force: true);
_checkBonusStatus();
}
});
}
void _loadData() {
@@ -48,10 +70,10 @@ class _HomePageState extends State<HomePage>
Future<void> _checkBonusStatus() async {
try {
final bonusService = context.read<BonusService>();
final response = await bonusService.getStatus();
final response = await bonusService.getWelfareStatus();
if (response.success && response.data != null) {
setState(() {
_bonusClaimed = response.data!['claimed'] == true;
_totalClaimable = response.data!['totalClaimable'] as int? ?? 0;
});
}
} catch (_) {}
@@ -89,11 +111,13 @@ class _HomePageState extends State<HomePage>
onDeposit: _showDeposit,
),
SizedBox(height: AppSpacing.md),
// 新人福利卡片
_BonusCard(
isClaimed: _bonusClaimed,
onClaim: _claimBonus,
isLoading: _bonusLoading,
// 福利中心入口卡片
_WelfareCard(
totalClaimable: _totalClaimable,
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const WelfareCenterPage()),
),
),
SizedBox(height: AppSpacing.lg),
// 持仓
@@ -384,64 +408,11 @@ class _HomePageState extends State<HomePage>
mainState?.switchToTab(3);
}
Future<void> _claimBonus() async {
setState(() => _bonusLoading = true);
try {
final bonusService = context.read<BonusService>();
final response = await bonusService.claim();
if (!mounted) return;
if (response.success) {
setState(() => _bonusClaimed = true);
context.read<AssetProvider>().refreshAll(force: true);
showShadDialog(
context: context,
builder: (ctx) => ShadDialog.alert(
title: const Text('领取成功'),
description:
Text('50 USDT 已到账,请划转至交易账户后即可开始交易'),
actions: [
ShadButton(
child: const Text('确定'),
onPressed: () => Navigator.of(ctx).pop(),
),
],
),
);
} else {
showShadDialog(
context: context,
builder: (ctx) => ShadDialog.alert(
title: const Text('领取失败'),
description: Text(response.message ?? '请稍后重试'),
actions: [
ShadButton(
child: const Text('确定'),
onPressed: () => Navigator.of(ctx).pop(),
),
],
),
);
}
} catch (e) {
if (mounted) {
showShadDialog(
context: context,
builder: (ctx) => ShadDialog.alert(
title: const Text('领取失败'),
description: Text(e.toString()),
actions: [
ShadButton(
child: const Text('确定'),
onPressed: () => Navigator.of(ctx).pop(),
),
],
),
);
}
} finally {
if (mounted) setState(() => _bonusLoading = false);
}
void _navigateToWelfareCenter() {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const WelfareCenterPage()),
);
}
}
@@ -963,120 +934,122 @@ class _AssetCardState extends State<_AssetCard> {
}
}
/// 新人福利卡片
class _BonusCard extends StatelessWidget {
final bool isClaimed;
final VoidCallback onClaim;
final bool isLoading;
/// 福利中心入口卡片
class _WelfareCard extends StatelessWidget {
final int totalClaimable;
final VoidCallback onTap;
const _BonusCard({required this.isClaimed, required this.onClaim, required this.isLoading});
const _WelfareCard({required this.totalClaimable, required this.onTap});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Opacity(
opacity: isClaimed ? 0.6 : 1.0,
child: GestureDetector(
onTap: isClaimed || isLoading ? null : onClaim,
child: Container(
width: double.infinity,
padding: EdgeInsets.all(AppSpacing.lg),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
colorScheme.primary.withOpacity(0.15),
colorScheme.secondary.withOpacity(0.1),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(AppRadius.xl),
border: Border.all(color: colorScheme.primary.withOpacity(0.2)),
),
child: Row(
children: [
// 左侧图标
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: isClaimed
? colorScheme.onSurfaceVariant.withOpacity(0.1)
: colorScheme.primary.withOpacity(0.15),
borderRadius: BorderRadius.circular(AppRadius.lg),
),
child: Icon(
isClaimed ? LucideIcons.check : LucideIcons.gift,
color: isClaimed ? AppColorScheme.up : colorScheme.primary,
size: 24,
),
),
SizedBox(width: AppSpacing.md),
// 中间文字
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'新人福利',
style: GoogleFonts.spaceGrotesk(
fontSize: 16,
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
SizedBox(height: AppSpacing.xs),
Text(
isClaimed ? '50 USDT 体验金已到账' : '领取 50 USDT 体验金,开始您的交易之旅',
style: TextStyle(
fontSize: 12,
color: colorScheme.onSurfaceVariant,
),
),
],
),
),
// 右侧按钮
Container(
padding: EdgeInsets.symmetric(
horizontal: AppSpacing.md,
vertical: AppSpacing.sm,
),
decoration: BoxDecoration(
color: isClaimed
? colorScheme.onSurfaceVariant.withOpacity(0.15)
: null,
gradient: isClaimed
? null
: (isDark
? AppColorScheme.darkCtaGradient
: AppColorScheme.lightCtaGradient),
borderRadius: BorderRadius.circular(AppRadius.full),
),
child: isLoading
? SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
color: isDark ? colorScheme.background : Colors.white,
),
)
: Text(
isClaimed ? '已领取' : '立即领取',
style: TextStyle(
color: isClaimed
? colorScheme.onSurfaceVariant
: (isDark ? colorScheme.background : Colors.white),
fontSize: 13,
fontWeight: FontWeight.w700,
),
),
),
return GestureDetector(
onTap: onTap,
child: Container(
width: double.infinity,
padding: EdgeInsets.all(AppSpacing.lg),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
colorScheme.primary.withOpacity(0.15),
colorScheme.secondary.withOpacity(0.1),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(AppRadius.xl),
border: Border.all(color: colorScheme.primary.withOpacity(0.2)),
),
child: Row(
children: [
// 左侧图标
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: colorScheme.primary.withOpacity(0.15),
borderRadius: BorderRadius.circular(AppRadius.lg),
),
child: Icon(
LucideIcons.gift,
color: colorScheme.primary,
size: 24,
),
),
SizedBox(width: AppSpacing.md),
// 中间文字
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'福利中心',
style: GoogleFonts.spaceGrotesk(
fontSize: 16,
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
),
),
SizedBox(height: AppSpacing.xs),
Text(
totalClaimable > 0
? '您有 $totalClaimable 个奖励待领取'
: '首充奖励 + 推广奖励',
style: TextStyle(
fontSize: 12,
color: colorScheme.onSurfaceVariant,
),
),
],
),
),
// 右侧按钮
Container(
padding: EdgeInsets.symmetric(
horizontal: AppSpacing.md,
vertical: AppSpacing.sm,
),
decoration: BoxDecoration(
gradient: isDark
? AppColorScheme.darkCtaGradient
: AppColorScheme.lightCtaGradient,
borderRadius: BorderRadius.circular(AppRadius.full),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (totalClaimable > 0)
Container(
padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10),
),
child: Text(
'$totalClaimable',
style: TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(width: totalClaimable > 0 ? 6 : 0),
Text(
'查看',
style: TextStyle(
color: isDark ? colorScheme.background : Colors.white,
fontSize: 13,
fontWeight: FontWeight.w700,
),
),
],
),
),
],
),
),
);