rwadurian/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart

491 lines
16 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/constants/app_colors.dart';
import '../../../core/utils/format_utils.dart';
import '../../providers/user_providers.dart';
import '../../providers/contribution_providers.dart';
class ContributionPage extends ConsumerWidget {
const ContributionPage({super.key});
// 设计色彩
static const Color _orange = Color(0xFFFF6B00);
static const Color _green = Color(0xFF22C55E);
static const Color _grayText = Color(0xFF6B7280);
static const Color _darkText = Color(0xFF1F2937);
static const Color _bgGray = Color(0xFFF3F4F6);
static const Color _lightGray = Color(0xFFF9FAFB);
@override
Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userNotifierProvider);
final accountSequence = user.accountSequence ?? '';
final contributionAsync = ref.watch(contributionProvider(accountSequence));
return Scaffold(
backgroundColor: const Color(0xFFF5F5F5),
body: SafeArea(
child: RefreshIndicator(
onRefresh: () async {
ref.invalidate(contributionProvider(accountSequence));
},
child: contributionAsync.when(
data: (contribution) {
return CustomScrollView(
slivers: [
// 顶部导航栏
SliverToBoxAdapter(child: _buildAppBar(context)),
// 内容
SliverPadding(
padding: const EdgeInsets.all(16),
sliver: SliverList(
delegate: SliverChildListDelegate([
// 总贡献值卡片
_buildTotalContributionCard(contribution),
const SizedBox(height: 16),
// 三栏统计
_buildThreeColumnStats(contribution),
const SizedBox(height: 16),
// 今日预估收益
_buildTodayEstimateCard(contribution),
const SizedBox(height: 16),
// 贡献值明细
_buildContributionDetailCard(contribution),
const SizedBox(height: 16),
// 团队层级统计
_buildTeamStatsCard(contribution),
const SizedBox(height: 16),
// 贡献值失效倒计时
_buildExpirationCard(contribution),
const SizedBox(height: 24),
]),
),
),
],
);
},
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, _) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, size: 48, color: AppColors.error),
const SizedBox(height: 16),
Text('加载失败: $error'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => ref.invalidate(contributionProvider(accountSequence)),
child: const Text('重试'),
),
],
),
),
),
),
),
);
}
Widget _buildAppBar(BuildContext context) {
return Container(
color: _lightGray,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
// Logo
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: _orange.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: const Icon(Icons.eco, color: _orange, size: 20),
),
const SizedBox(width: 8),
const Text(
'榴莲生态',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: _darkText,
letterSpacing: 0.45,
),
),
const Spacer(),
// 客服
IconButton(
icon: const Icon(Icons.headset_mic_outlined, color: _grayText),
onPressed: () {},
),
// 通知(带红点)
Stack(
children: [
IconButton(
icon: const Icon(Icons.notifications_outlined, color: _grayText),
onPressed: () {},
),
Positioned(
right: 10,
top: 10,
child: Container(
width: 8,
height: 8,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
),
),
],
),
],
),
);
}
Widget _buildTotalContributionCard(contribution) {
final total = contribution?.effectiveContribution ?? '0';
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'总贡献值',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _grayText),
),
Icon(Icons.visibility_outlined, color: _grayText.withOpacity(0.5), size: 18),
],
),
const SizedBox(height: 8),
Text(
formatAmount(total),
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: _orange,
letterSpacing: -0.75,
),
),
const SizedBox(height: 12),
// 有效期标签
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: _lightGray,
borderRadius: BorderRadius.circular(999),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.info_outline, size: 14, color: _grayText.withOpacity(0.7)),
const SizedBox(width: 6),
Text(
'贡献值有效期: 剩余 730 天',
style: TextStyle(fontSize: 12, color: _grayText.withOpacity(0.9)),
),
],
),
),
],
),
);
}
Widget _buildThreeColumnStats(contribution) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Row(
children: [
_buildStatColumn('个人贡献值', contribution?.personalContribution ?? '0', false),
_buildStatColumn('团队贡献值', contribution?.teamLevelContribution ?? '0', true),
_buildStatColumn('省市公司', contribution?.systemContribution ?? '0', true),
],
),
);
}
Widget _buildStatColumn(String label, String value, bool showLeftBorder) {
return Expanded(
child: Container(
decoration: showLeftBorder
? const BoxDecoration(
border: Border(left: BorderSide(color: Color(0xFFE5E7EB), width: 1)),
)
: null,
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Column(
children: [
Text(label, style: const TextStyle(fontSize: 12, color: _grayText)),
const SizedBox(height: 4),
Text(
formatAmount(value),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: _darkText),
),
],
),
),
);
}
Widget _buildTodayEstimateCard(contribution) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Row(
children: [
// 图标
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: _green.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: const Icon(Icons.trending_up, color: _green, size: 24),
),
const SizedBox(width: 12),
// 文字说明
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'今日预估收益',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _grayText),
),
Text(
'基于当前贡献值占比计算',
style: TextStyle(fontSize: 12, color: _grayText.withOpacity(0.7)),
),
],
),
),
// 收益数值
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: const [
Text.rich(
TextSpan(
children: [
TextSpan(
text: '+156.78 ',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: _green),
),
TextSpan(
text: '积分',
style: TextStyle(fontSize: 12, color: _green),
),
],
),
),
Text('', style: TextStyle(fontSize: 12, color: _green)),
],
),
],
),
);
}
Widget _buildContributionDetailCard(contribution) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
// 标题行
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'贡献值明细',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _darkText),
),
GestureDetector(
onTap: () {},
child: Row(
children: const [
Text('查看全部', style: TextStyle(fontSize: 12, color: _orange)),
Icon(Icons.chevron_right, size: 14, color: _orange),
],
),
),
],
),
const SizedBox(height: 16),
// 明细列表
_buildDetailRow('认种榴莲树', '2024-01-15 14:30', '+22,617.00'),
const Divider(height: 24),
_buildDetailRow('团队奖励(5级)', '2024-01-15 09:12', '+1,130.85'),
const Divider(height: 24),
_buildDetailRow('直推奖励', '2024-01-14 18:45', '+565.43'),
],
),
);
}
Widget _buildDetailRow(String title, String time, String amount) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _darkText)),
const SizedBox(height: 2),
Text(time, style: const TextStyle(fontSize: 12, color: _grayText)),
],
),
Text(
amount,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _green),
),
],
);
}
Widget _buildTeamStatsCard(contribution) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'团队层级统计',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _darkText),
),
const SizedBox(height: 16),
// 第一行
Row(
children: [
_buildTeamStatItem('直推人数', '${contribution?.directReferralAdoptedCount ?? 0}', ''),
const SizedBox(width: 16),
_buildTeamStatItem('团队总人数', '128', ''),
],
),
const SizedBox(height: 16),
// 第二行
Row(
children: [
_buildTeamStatItem('已解锁层级', '${contribution?.unlockedLevelDepth ?? 0}', ''),
const SizedBox(width: 16),
_buildTeamStatItem('团队认种总数', '456', ''),
],
),
],
),
);
}
Widget _buildTeamStatItem(String label, String value, String unit) {
return Expanded(
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: _bgGray,
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: const TextStyle(fontSize: 12, color: _grayText)),
const SizedBox(height: 4),
Text.rich(
TextSpan(
children: [
TextSpan(
text: '$value ',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: _orange),
),
TextSpan(
text: unit,
style: const TextStyle(fontSize: 12, color: _grayText),
),
],
),
),
],
),
),
);
}
Widget _buildExpirationCard(contribution) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 标题
Row(
children: const [
Icon(Icons.timer_outlined, color: _orange, size: 24),
SizedBox(width: 8),
Text(
'贡献值失效倒计时',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _darkText),
),
],
),
const SizedBox(height: 12),
// 进度条
ClipRRect(
borderRadius: BorderRadius.circular(5),
child: LinearProgressIndicator(
value: 0.8,
minHeight: 10,
backgroundColor: _bgGray,
valueColor: const AlwaysStoppedAnimation<Color>(_orange),
),
),
const SizedBox(height: 12),
// 说明文字
const Text(
'您的贡献值将于 2026-01-15 失效',
style: TextStyle(fontSize: 12, color: _grayText),
),
const SizedBox(height: 8),
// 提示
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: _bgGray,
borderRadius: BorderRadius.circular(4),
),
child: const Text(
'* 运营账号贡献值永不失效',
style: TextStyle(fontSize: 10, color: _orange),
),
),
],
),
);
}
}