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

1438 lines
43 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 '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 '../../../../core/di/injection_container.dart';
import '../../../../routes/route_paths.dart';
import 'dart:async';
/// 个人中心页面 - 显示用户信息、社区数据、收益和设置
/// 包含用户资料、推荐信息、社区考核、收益领取等功能
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 = '--'; // 我的推荐码
final String _community = '星空社区';
final String _parentCommunity = '银河社区';
final String _childCommunity = '星辰社区';
final String _cityCompany = '深圳公司';
final String _provinceCompany = '广东公司';
final String _province = '广东';
// 团队数据
final int _teamUsers = 1204;
final int _teamPlanting = 8930;
// 直推数据
final List<Map<String, dynamic>> _referrals = [
{'serial': '87654321', 'personal': 15, 'team': 120},
{'serial': '87654322', 'personal': 10, 'team': 85},
{'serial': '87654323', 'personal': 25, 'team': 250},
];
// 社区考核数据
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
@override
void initState() {
super.initState();
_startCountdown();
// 先同步检查本地头像,再异步加载其他数据
_checkLocalAvatarSync();
_loadUserData();
}
/// 同步检查本地头像文件(在 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');
// 失败时保持现有数据,不影响页面显示
}
}
/// 后台下载并缓存头像
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 _copyShareLink() {
Clipboard.setData(ClipboardData(text: 'https://rwa.app/invite/$_serialNumber'));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('分享链接已复制'),
backgroundColor: Color(0xFFD4AF37),
),
);
}
/// 领取全部收益
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: Text(
'推荐人的序列号:',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xCC5D4037),
),
),
),
Expanded(
child: Text(
'下级社区:',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xCC5D4037),
),
),
),
],
),
const SizedBox(height: 4),
Row(
children: [
Expanded(
child: Text(
'所属社区:',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xCC5D4037),
),
),
),
Expanded(
child: Text(
'授权市公司:',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xCC5D4037),
),
),
),
],
),
const SizedBox(height: 4),
Row(
children: [
Expanded(
child: Text(
'上级社区:',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xCC5D4037),
),
),
),
Expanded(
child: Text(
'授权省公司:',
style: const TextStyle(
fontSize: 14,
fontFamily: 'Inter',
height: 1.5,
color: Color(0xCC5D4037),
),
),
),
],
),
],
),
);
}
/// 构建社区/省份标签
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),
// 复制分享链接
_buildCopyShareButton(),
const SizedBox(height: 16),
// 社区权益考核
_buildCommunityAssessment(),
const SizedBox(height: 16),
// 设置菜单
_buildSettingsMenu(),
],
),
);
}
/// 构建收益区域
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(_teamUsers),
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(_teamPlanting),
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 _buildCopyShareButton() {
return GestureDetector(
onTap: _copyShareLink,
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),
),
],
),
),
);
}
}