rwadurian/frontend/mobile-app/lib/features/profile/presentation/pages/profile_page.dart

1644 lines
49 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:go_router/go_router.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';
import '../../../../core/di/injection_container.dart';
import '../../../../core/services/referral_service.dart';
import '../../../../routes/route_paths.dart';
import '../../../../routes/app_router.dart';
/// 个人中心页面 - 显示用户信息、社区数据、收益和设置
/// 包含用户资料、推荐信息、社区考核、收益领取等功能
class ProfilePage extends ConsumerStatefulWidget {
const ProfilePage({super.key});
@override
ConsumerState<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends ConsumerState<ProfilePage> {
// 用户数据(从存储/API加载
String _nickname = '加载中...';
String _serialNumber = '--';
String? _avatarSvg;
String? _avatarUrl;
String? _localAvatarPath; // 本地头像文件路径
String _referrerSerial = '--'; // 推荐人序列号从API获取
String _referralCode = '--'; // 我的推荐码
// 授权数据(从 authorization-service 获取)
String _community = '--';
String _parentCommunity = '--';
String _childCommunity = '--';
String _cityCompany = '--';
String _provinceCompany = '--';
String _province = '--';
// 团队数据(从 referral-service 获取)
int _directReferralCount = 0;
int _totalTeamCount = 0;
int _personalPlantingCount = 0;
int _teamPlantingCount = 0;
double _leaderboardScore = 0;
int? _leaderboardRank;
// 直推数据(从 referral-service 获取)
List<Map<String, dynamic>> _referrals = [];
// 社区考核数据
final int _communityLevel = 3;
final int _currentPlanting = 12;
final int _requiredPlanting = 50;
// 收益数据
final double _pendingUsdt = 320.75;
final double _pendingPower = 50.00;
final double _settleableUsdt = 1500.00;
final double _settledUsdt = 8500.50;
final double _expiredUsdt = 250.00;
final double _expiredPower = 15.00;
// 倒计时
Timer? _timer;
int _remainingSeconds = 66942; // 18:35:42
// 应用版本信息
String _appVersion = '--';
String _buildNumber = '--';
String _packageName = '--';
String _deviceModel = '--';
String _osVersion = '--';
String _platform = '--';
@override
void initState() {
super.initState();
_startCountdown();
// 先同步检查本地头像,再异步加载其他数据
_checkLocalAvatarSync();
_loadUserData();
_loadAppInfo();
// 加载推荐和授权数据
_loadReferralData();
_loadAuthorizationData();
}
/// 加载应用信息
Future<void> _loadAppInfo() async {
try {
// 加载包信息
final packageInfo = await PackageInfo.fromPlatform();
// 加载设备信息
final deviceInfoPlugin = DeviceInfoPlugin();
String deviceModel = '';
String osVersion = '';
String platform = '';
if (Platform.isAndroid) {
final androidInfo = await deviceInfoPlugin.androidInfo;
deviceModel = '${androidInfo.brand} ${androidInfo.model}';
osVersion = 'Android ${androidInfo.version.release} (SDK ${androidInfo.version.sdkInt})';
platform = 'Android';
} else if (Platform.isIOS) {
final iosInfo = await deviceInfoPlugin.iosInfo;
deviceModel = iosInfo.model;
osVersion = '${iosInfo.systemName} ${iosInfo.systemVersion}';
platform = 'iOS';
}
if (mounted) {
setState(() {
_appVersion = packageInfo.version;
_buildNumber = packageInfo.buildNumber;
_packageName = packageInfo.packageName;
_deviceModel = deviceModel;
_osVersion = osVersion;
_platform = platform;
});
}
} catch (e) {
debugPrint('[ProfilePage] 加载应用信息失败: $e');
}
}
/// 同步检查本地头像文件(在 build 之前快速获取)
void _checkLocalAvatarSync() {
// 使用 WidgetsBinding 确保在第一帧渲染前执行
WidgetsBinding.instance.addPostFrameCallback((_) async {
final accountService = ref.read(accountServiceProvider);
final localPath = await accountService.getLocalAvatarPath();
if (mounted && localPath != null && _localAvatarPath == null) {
setState(() {
_localAvatarPath = localPath;
});
}
});
}
/// 加载用户数据
Future<void> _loadUserData() async {
final accountService = ref.read(accountServiceProvider);
// 并行加载本地存储数据
final results = await Future.wait([
accountService.getUsername(),
accountService.getUserSerialNum(),
accountService.getAvatarSvg(),
accountService.getAvatarUrl(),
accountService.getLocalAvatarPath(),
accountService.getReferralCode(),
]);
final username = results[0] as String?;
final serialNum = results[1] as int?;
final avatarSvg = results[2] as String?;
final avatarUrl = results[3] as String?;
final localAvatarPath = results[4] as String?;
final referralCode = results[5] as String?;
if (mounted) {
setState(() {
_nickname = username ?? '未设置昵称';
_serialNumber = serialNum?.toString() ?? '--';
_avatarSvg = avatarSvg;
_avatarUrl = avatarUrl;
_localAvatarPath = localAvatarPath;
_referralCode = referralCode ?? '--';
});
// 如果有远程URL但没有本地缓存后台下载并缓存
if (avatarUrl != null && avatarUrl.isNotEmpty && localAvatarPath == null) {
_downloadAndCacheAvatar(avatarUrl);
}
}
// 从API获取完整用户信息包括推荐人
_loadMeData();
}
/// 从API加载完整用户信息
Future<void> _loadMeData() async {
try {
final accountService = ref.read(accountServiceProvider);
final meData = await accountService.getMe();
if (mounted) {
setState(() {
_referrerSerial = meData.inviterSequence?.toString() ?? '';
// 如果API返回了更新的数据也更新本地显示
if (meData.nickname.isNotEmpty) {
_nickname = meData.nickname;
}
if (meData.referralCode.isNotEmpty) {
_referralCode = meData.referralCode;
}
});
}
} catch (e) {
debugPrint('[ProfilePage] 加载用户信息失败: $e');
// 失败时保持现有数据,不影响页面显示
}
}
/// 加载推荐数据 (from referral-service)
Future<void> _loadReferralData() async {
try {
final referralService = ref.read(referralServiceProvider);
// 并行加载推荐信息和直推列表
final results = await Future.wait([
referralService.getMyReferralInfo(),
referralService.getDirectReferrals(limit: 10),
]);
final referralInfo = results[0] as ReferralInfoResponse;
final directReferrals = results[1] as DirectReferralsResponse;
if (mounted) {
setState(() {
_directReferralCount = referralInfo.directReferralCount;
_totalTeamCount = referralInfo.totalTeamCount;
_personalPlantingCount = referralInfo.personalPlantingCount;
_teamPlantingCount = referralInfo.teamPlantingCount;
_leaderboardScore = referralInfo.leaderboardScore;
_leaderboardRank = referralInfo.leaderboardRank;
// 转换直推列表格式
_referrals = directReferrals.referrals.map((r) => {
'serial': r.userId,
'personal': 0, // API暂未返回个人认种量
'team': r.teamCount,
}).toList();
});
}
} catch (e) {
debugPrint('[ProfilePage] 加载推荐数据失败: $e');
// 失败时保持默认数据
}
}
/// 加载授权数据 (from authorization-service)
Future<void> _loadAuthorizationData() async {
try {
final authorizationService = ref.read(authorizationServiceProvider);
final summary = await authorizationService.getMyAuthorizationSummary();
if (mounted) {
setState(() {
_community = summary.communityName ?? '--';
_cityCompany = summary.cityCompanyName ?? '--';
_provinceCompany = summary.provinceCompanyName ?? '--';
// 上级社区和下级社区暂时无法从当前API获取
// 后续需要扩展API或从推荐链中计算
});
}
} catch (e) {
debugPrint('[ProfilePage] 加载授权数据失败: $e');
// 失败时保持默认数据
}
}
/// 后台下载并缓存头像
Future<void> _downloadAndCacheAvatar(String url) async {
final accountService = ref.read(accountServiceProvider);
final localPath = await accountService.downloadAndCacheAvatar(url);
if (mounted && localPath != null) {
setState(() {
_localAvatarPath = localPath;
});
}
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
/// 开始倒计时
void _startCountdown() {
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (_remainingSeconds > 0) {
setState(() {
_remainingSeconds--;
});
}
});
}
/// 格式化倒计时
String _formatCountdown() {
final hours = (_remainingSeconds ~/ 3600).toString().padLeft(2, '0');
final minutes = ((_remainingSeconds % 3600) ~/ 60).toString().padLeft(2, '0');
final seconds = (_remainingSeconds % 60).toString().padLeft(2, '0');
return '$hours : $minutes : $seconds';
}
/// 复制序列号
void _copySerialNumber() {
Clipboard.setData(ClipboardData(text: _serialNumber));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('序列号已复制'),
backgroundColor: Color(0xFFD4AF37),
),
);
}
/// 跳转到分享页面
void _goToSharePage() {
context.push(
RoutePaths.share,
extra: SharePageParams(
shareLink: 'https://s3.szaiai.com/rwadurian/app-release.apk',
referralCode: _referralCode,
),
);
}
/// 领取全部收益
void _claimAllEarnings() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('确认领取'),
content: Text(
'确定领取全部收益吗?\nUSDT: ${_formatNumber(_pendingUsdt)}\n算力: ${_formatNumber(_pendingPower)}',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消'),
),
TextButton(
onPressed: () {
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('领取成功'),
backgroundColor: Color(0xFFD4AF37),
),
);
},
child: const Text('确认'),
),
],
),
);
}
/// 结算
void _onSettlement() {
context.go(RoutePaths.trading);
}
/// 充值USDT
void _onDeposit() {
context.push(RoutePaths.depositUsdt);
}
/// 进入交易
void _goToTrading() {
context.go(RoutePaths.trading);
}
/// 进入认种
void _goToPlanting() {
context.push(RoutePaths.plantingQuantity);
}
/// 谷歌验证器
void _goToGoogleAuth() {
context.push(RoutePaths.googleAuth);
}
/// 修改密码
void _goToChangePassword() {
context.push(RoutePaths.changePassword);
}
/// 绑定邮箱
void _goToBindEmail() {
context.push(RoutePaths.bindEmail);
}
/// 编辑资料
Future<void> _goToEditProfile() async {
final result = await context.push<bool>(RoutePaths.editProfile);
// 如果编辑页面返回 true说明有更新刷新用户数据
if (result == true && mounted) {
_loadUserData();
}
}
/// 格式化数字
String _formatNumber(double number) {
final parts = number.toStringAsFixed(2).split('.');
final intPart = parts[0].replaceAllMapped(
RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'),
(Match m) => '${m[1]},',
);
return '$intPart.${parts[1]}';
}
/// 格式化整数
String _formatInt(int number) {
return number.toString().replaceAllMapped(
RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'),
(Match m) => '${m[1]},',
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFFFF5E6),
Color(0xFFFFE4B5),
],
),
),
child: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 16),
// 用户头像和基本信息
_buildUserHeader(),
const SizedBox(height: 16),
// 推荐人信息卡片
_buildReferralInfoCard(),
const SizedBox(height: 16),
// 社区/省份标签
_buildCommunityLabel(),
const SizedBox(height: 8),
// 认种按钮
_buildPlantingButton(),
const SizedBox(height: 16),
// 主要内容卡片
_buildMainContentCard(),
const SizedBox(height: 24),
],
),
),
),
),
),
);
}
/// 构建用户头像和基本信息
Widget _buildUserHeader() {
return Row(
children: [
// 头像(点击跳转到编辑资料页面)
GestureDetector(
onTap: _goToEditProfile,
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
color: const Color(0xFFFFF5E6),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(40),
child: _buildAvatarContent(),
),
),
),
const SizedBox(width: 16),
// 用户信息
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_nickname,
style: const TextStyle(
fontSize: 20,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
letterSpacing: -0.3,
color: Color(0xFF5D4037),
),
),
const SizedBox(height: 3),
Row(
children: [
Text(
'序列号: $_serialNumber',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xCC5D4037),
),
),
const SizedBox(width: 8),
GestureDetector(
onTap: _copySerialNumber,
child: const Icon(
Icons.copy,
size: 16,
color: Color(0xCC5D4037),
),
),
],
),
],
),
),
],
);
}
/// 构建头像内容优先本地文件其次网络URL最后SVG
Widget _buildAvatarContent() {
// 1. 优先显示本地缓存的头像文件
if (_localAvatarPath != null && _localAvatarPath!.isNotEmpty) {
final file = File(_localAvatarPath!);
// 同步检查文件是否存在
if (file.existsSync()) {
return Image.file(
file,
width: 80,
height: 80,
fit: BoxFit.cover,
gaplessPlayback: true, // 防止图片切换时闪烁
errorBuilder: (context, error, stackTrace) {
// 本地文件加载失败尝试网络URL
return _buildNetworkOrSvgAvatar();
},
);
}
}
// 2. 没有本地缓存尝试网络URL或SVG
return _buildNetworkOrSvgAvatar();
}
/// 构建网络URL或SVG头像
Widget _buildNetworkOrSvgAvatar() {
// 尝试显示网络图片URL
if (_avatarUrl != null && _avatarUrl!.isNotEmpty) {
return Image.network(
_avatarUrl!,
width: 80,
height: 80,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return const Center(
child: SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFFD4AF37)),
),
),
);
},
errorBuilder: (context, error, stackTrace) {
// 加载失败时显示SVG或默认头像
return _buildSvgOrDefaultAvatar();
},
);
}
// 显示SVG或默认头像
return _buildSvgOrDefaultAvatar();
}
/// 构建SVG或默认头像
Widget _buildSvgOrDefaultAvatar() {
if (_avatarSvg != null) {
return SvgPicture.string(
_avatarSvg!,
width: 80,
height: 80,
fit: BoxFit.cover,
);
}
return const Icon(
Icons.person,
size: 40,
color: Color(0xFF8B5A2B),
);
}
/// 构建推荐人信息卡片
Widget _buildReferralInfoCard() {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0x80FFFFFF),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 第一行:推荐人序列号 | 下级社区
Row(
children: [
Expanded(
child: _buildInfoItem('推荐人的序列号', _referrerSerial),
),
Expanded(
child: _buildInfoItem('下级社区', _childCommunity),
),
],
),
const SizedBox(height: 12),
// 第二行:所属社区 | 授权市公司
Row(
children: [
Expanded(
child: _buildInfoItem('所属社区', _community),
),
Expanded(
child: _buildInfoItem('授权市公司', _cityCompany),
),
],
),
const SizedBox(height: 12),
// 第三行:上级社区 | 授权省公司
Row(
children: [
Expanded(
child: _buildInfoItem('上级社区', _parentCommunity),
),
Expanded(
child: _buildInfoItem('授权省公司', _provinceCompany),
),
],
),
],
),
);
}
/// 构建信息项(标签 + 值)
Widget _buildInfoItem(String label, String value) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'$label:',
style: const TextStyle(
fontSize: 12,
fontFamily: 'Inter',
height: 1.5,
color: Color(0x995D4037),
),
),
const SizedBox(height: 2),
Text(
value,
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w600,
height: 1.5,
color: Color(0xFF5D4037),
),
),
],
);
}
/// 构建社区/省份标签
Widget _buildCommunityLabel() {
return const Text(
'社区 / 省份',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xFF5D4037),
),
);
}
/// 构建认种按钮
Widget _buildPlantingButton() {
return GestureDetector(
onTap: _goToPlanting,
child: Container(
width: double.infinity,
height: 48,
decoration: BoxDecoration(
color: const Color(0xFFD4AF37),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Text(
'认种 / Planting',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
letterSpacing: 0.24,
color: Colors.white,
),
),
),
),
);
}
/// 构建主要内容卡片
Widget _buildMainContentCard() {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0x80FFFFFF),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
children: [
// 收益区域
_buildEarningsSection(),
const SizedBox(height: 16),
// 结算区域
_buildSettlementSection(),
const SizedBox(height: 16),
// 已过期区域
_buildExpiredSection(),
const SizedBox(height: 16),
// 操作按钮
_buildActionButtons(),
const SizedBox(height: 16),
// 团队统计
_buildTeamStats(),
const SizedBox(height: 16),
// 直推列表
_buildReferralList(),
const SizedBox(height: 16),
// 分享邀请按钮
_buildShareButton(),
const SizedBox(height: 16),
// 社区权益考核
_buildCommunityAssessment(),
const SizedBox(height: 16),
// 设置菜单
_buildSettingsMenu(),
const SizedBox(height: 16),
// 应用版本信息
_buildAppVersionInfo(),
],
),
);
}
/// 构建收益区域
Widget _buildEarningsSection() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFFFF5E6),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 倒计时
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'24 小时倒计时',
style: TextStyle(
fontSize: 12,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
),
Text(
_formatCountdown(),
style: const TextStyle(
fontSize: 14,
fontFamily: 'Consolas',
fontWeight: FontWeight.w700,
height: 1.25,
letterSpacing: 0.7,
color: Color(0xFFD4AF37),
),
),
],
),
const SizedBox(height: 15),
// 待领取 USDT
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'待领取 (USDT)',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
),
Text(
_formatNumber(_pendingUsdt),
style: const TextStyle(
fontSize: 20,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037),
),
),
],
),
const SizedBox(height: 11),
// 待领取 算力
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'待领取 (算力)',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
),
Text(
_formatNumber(_pendingPower),
style: const TextStyle(
fontSize: 20,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037),
),
),
],
),
const SizedBox(height: 15),
// 领取全部按钮
GestureDetector(
onTap: _claimAllEarnings,
child: Container(
width: double.infinity,
height: 40,
decoration: BoxDecoration(
color: const Color(0xFFD4AF37),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Text(
'领取全部',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
letterSpacing: 0.21,
color: Colors.white,
),
),
),
),
),
],
),
);
}
/// 构建结算区域
Widget _buildSettlementSection() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFFFF5E6),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 可结算 USDT
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'可结算 (USDT)',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
),
Text(
_formatNumber(_settleableUsdt),
style: const TextStyle(
fontSize: 20,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037),
),
),
],
),
const SizedBox(height: 11),
// 已结算 USDT
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'已结算 (USDT)',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
),
GestureDetector(
onTap: _onSettlement,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 7),
decoration: BoxDecoration(
color: const Color(0xFFD4AF37),
borderRadius: BorderRadius.circular(4),
),
child: const Text(
'结算',
style: TextStyle(
fontSize: 12,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
letterSpacing: 0.18,
color: Colors.white,
),
),
),
),
],
),
const SizedBox(height: 4),
Text(
_formatNumber(_settledUsdt),
style: const TextStyle(
fontSize: 20,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037),
),
),
],
),
);
}
/// 构建已过期区域
Widget _buildExpiredSection() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFFFF5E6),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'已过期',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
color: Color(0xFF5D4037),
),
),
const SizedBox(height: 7),
// 已过期 USDT
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'已过期 (USDT)',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
),
Text(
_formatNumber(_expiredUsdt),
style: const TextStyle(
fontSize: 20,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037),
),
),
],
),
const SizedBox(height: 11),
// 已过期 算力
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'已过期 (算力)',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
),
Text(
_formatNumber(_expiredPower),
style: const TextStyle(
fontSize: 20,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037),
),
),
],
),
],
),
);
}
/// 构建操作按钮
Widget _buildActionButtons() {
return Column(
children: [
// 充值 USDT 按钮
GestureDetector(
onTap: _onDeposit,
child: Container(
width: double.infinity,
height: 48,
decoration: BoxDecoration(
color: const Color(0xFFD4AF37),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Text(
'充值 USDT (KAVA / BSC)',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
letterSpacing: 0.24,
color: Colors.white,
),
),
),
),
),
const SizedBox(height: 12),
// 进入交易按钮
GestureDetector(
onTap: _goToTrading,
child: Container(
width: double.infinity,
height: 48,
decoration: BoxDecoration(
color: const Color(0xFF8B5A2B),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: Text(
'进入交易 (卖出 DST → USDT)',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
letterSpacing: 0.24,
color: Colors.white,
),
),
),
),
),
],
);
}
/// 构建团队统计
Widget _buildTeamStats() {
return Row(
children: [
Expanded(
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFFFF5E6),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
children: [
const Text(
'直推人数',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
_formatInt(_directReferralCount),
style: const TextStyle(
fontSize: 24,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037),
),
textAlign: TextAlign.center,
),
],
),
),
),
const SizedBox(width: 16),
Expanded(
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFFFF5E6),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
children: [
const Text(
'团队种植数量',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xCC5D4037),
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
_formatInt(_totalTeamCount),
style: const TextStyle(
fontSize: 24,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.25,
color: Color(0xFF5D4037),
),
textAlign: TextAlign.center,
),
],
),
),
),
],
);
}
/// 构建直推列表
Widget _buildReferralList() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.only(top: 8),
child: Text(
'直推列表',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
color: Color(0xFF5D4037),
),
),
),
const SizedBox(height: 8),
..._referrals.map((referral) => Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xCCFFF5E6),
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'序列号: ${referral['serial']}',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.43,
color: Color(0xFF5D4037),
),
),
Text(
'个人/团队: ${referral['personal']} / ${referral['team']}',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.43,
color: Color(0xCC5D4037),
),
),
],
),
),
)),
],
);
}
/// 构建分享按钮
Widget _buildShareButton() {
return GestureDetector(
onTap: _goToSharePage,
child: Container(
width: double.infinity,
height: 48,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: const Color(0x33D4AF37),
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(
Icons.share,
size: 24,
color: Color(0xFFD4AF37),
),
SizedBox(width: 8),
Text(
'分享邀请',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.5,
letterSpacing: 0.24,
color: Color(0xFFD4AF37),
),
),
],
),
),
);
}
/// 构建社区权益考核
Widget _buildCommunityAssessment() {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0x80FFFFFF),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'社区权益考核',
style: TextStyle(
fontSize: 18,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.56,
color: Color(0xFF5D4037),
),
),
const SizedBox(height: 15),
// 社区等级
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'社区等级',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xCC5D4037),
),
),
Text(
'Level $_communityLevel',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w700,
height: 1.43,
color: Color(0xFF5D4037),
),
),
],
),
const SizedBox(height: 16),
// 种植数量
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'种植数量 / 等级要求',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xCC5D4037),
),
),
Text(
'$_currentPlanting / $_requiredPlanting',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xFF5D4037),
),
),
],
),
const SizedBox(height: 4),
// 进度条
Container(
height: 6,
decoration: BoxDecoration(
color: const Color(0x33D4AF37),
borderRadius: BorderRadius.circular(3),
),
child: FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: _currentPlanting / _requiredPlanting,
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFD4AF37),
borderRadius: BorderRadius.circular(3),
),
),
),
),
const SizedBox(height: 16),
// 社区贡献奖励
Row(
children: const [
Text(
'社区贡献奖励',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xCC5D4037),
),
),
SizedBox(width: 39),
Expanded(
child: Text(
'有资格获得 3% 的社区福利',
style: TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.43,
color: Color(0xFFD4AF37),
),
),
),
],
),
],
),
);
}
/// 构建设置菜单
Widget _buildSettingsMenu() {
return Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: const Color(0x80FFFFFF),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
children: [
_buildSettingItem(
icon: Icons.verified_user,
title: '谷歌验证器',
onTap: _goToGoogleAuth,
),
_buildSettingItem(
icon: Icons.lock,
title: '修改登录密码',
onTap: _goToChangePassword,
),
_buildSettingItem(
icon: Icons.email,
title: '绑定邮箱',
onTap: _goToBindEmail,
),
],
),
);
}
/// 构建设置项
Widget _buildSettingItem({
required IconData icon,
required String title,
required VoidCallback onTap,
}) {
return GestureDetector(
onTap: onTap,
child: Container(
height: 48,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
child: Row(
children: [
Icon(
icon,
size: 24,
color: const Color(0xFF8B5A2B),
),
const SizedBox(width: 16),
Expanded(
child: Text(
title,
style: const TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xFF5D4037),
),
),
),
const Icon(
Icons.chevron_right,
size: 24,
color: Color(0xFF8B5A2B),
),
],
),
),
);
}
/// 构建应用版本信息
Widget _buildAppVersionInfo() {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFFFFF5E6),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: const Color(0x33D4AF37),
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 标题
const Row(
children: [
Icon(
Icons.info_outline,
size: 20,
color: Color(0xFF8B5A2B),
),
SizedBox(width: 8),
Text(
'应用信息',
style: TextStyle(
fontSize: 16,
fontFamily: 'Inter',
fontWeight: FontWeight.w600,
height: 1.5,
color: Color(0xFF5D4037),
),
),
],
),
const SizedBox(height: 12),
// 版本信息列表
_buildVersionInfoRow('应用版本', 'v$_appVersion'),
const SizedBox(height: 8),
_buildVersionInfoRow('构建号', _buildNumber),
const SizedBox(height: 8),
_buildVersionInfoRow('包名', _packageName),
const Divider(
height: 24,
color: Color(0x33D4AF37),
),
// 设备信息
_buildVersionInfoRow('设备型号', _deviceModel),
const SizedBox(height: 8),
_buildVersionInfoRow('系统版本', _osVersion),
const SizedBox(height: 8),
_buildVersionInfoRow('平台', _platform),
const SizedBox(height: 12),
// 版权信息
Center(
child: Text(
'© ${DateTime.now().year} RWADurian. All rights reserved.',
style: const TextStyle(
fontSize: 11,
fontFamily: 'Inter',
height: 1.5,
color: Color(0x995D4037),
),
),
),
],
),
);
}
/// 构建版本信息行
Widget _buildVersionInfoRow(String label, String value) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
label,
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xCC5D4037),
),
),
Flexible(
child: Text(
value,
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 1.5,
color: Color(0xFF5D4037),
),
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
),
),
],
);
}
}