491 lines
16 KiB
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),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|