Merge branch 'main' of http://8.155.172.147:3001/sion/monisuo
This commit is contained in:
Binary file not shown.
@@ -67,28 +67,70 @@ class _BillsPageState extends State<BillsPage> with SingleTickerProviderStateMix
|
|||||||
|
|
||||||
List<Map<String, dynamic>> _parseWelfareRecords(Map<String, dynamic> data) {
|
List<Map<String, dynamic>> _parseWelfareRecords(Map<String, dynamic> data) {
|
||||||
final records = <Map<String, dynamic>>[];
|
final records = <Map<String, dynamic>>[];
|
||||||
|
|
||||||
// 新人福利
|
// 新人福利
|
||||||
final newUser = data['newUserBonus'] as Map<String, dynamic>?;
|
final newUser = data['newUserBonus'] as Map<String, dynamic>?;
|
||||||
if (newUser != null) {
|
if (newUser != null) {
|
||||||
|
final claimed = newUser['claimed'] as bool? ?? false;
|
||||||
|
final eligible = newUser['eligible'] as bool? ?? false;
|
||||||
|
// 状态: 1=已领取, 0=可领取(待领取), 2=不可用(未解锁)
|
||||||
|
final int status;
|
||||||
|
if (claimed) {
|
||||||
|
status = 1;
|
||||||
|
} else if (eligible) {
|
||||||
|
status = 0;
|
||||||
|
} else {
|
||||||
|
status = 2;
|
||||||
|
}
|
||||||
records.add({
|
records.add({
|
||||||
'type': 'new_user',
|
'type': 'new_user',
|
||||||
'title': '新人福利',
|
'title': '新人福利',
|
||||||
'amount': newUser['amount']?.toString() ?? '0.00',
|
'amount': newUser['amount']?.toString() ?? '100.00',
|
||||||
'status': newUser['status'] ?? 0,
|
'status': status,
|
||||||
'time': newUser['claimTime'] ?? newUser['createTime'],
|
'time': newUser['claimTime'] ?? newUser['createTime'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 推广福利列表
|
// 推广福利列表
|
||||||
final referrals = data['referralBonuses'] as List?;
|
final referralRewards = data['referralRewards'] as List<dynamic>? ?? [];
|
||||||
if (referrals != null) {
|
for (var r in referralRewards) {
|
||||||
for (var r in referrals) {
|
final map = r as Map<String, dynamic>;
|
||||||
final map = r as Map<String, dynamic>;
|
final username = map['username'] as String? ?? '用户';
|
||||||
|
final milestones = map['milestones'] as List<dynamic>? ?? [];
|
||||||
|
final claimableCount = map['claimableCount'] as int? ?? 0;
|
||||||
|
|
||||||
|
// 每个 milestone 生成一条记录
|
||||||
|
for (var m in milestones) {
|
||||||
|
final ms = m as Map<String, dynamic>;
|
||||||
|
final earned = ms['earned'] as bool? ?? false;
|
||||||
|
final claimable = ms['claimable'] as bool? ?? false;
|
||||||
|
final milestoneVal = ms['milestone'] as int? ?? 1;
|
||||||
|
|
||||||
|
final int status;
|
||||||
|
if (earned) {
|
||||||
|
status = 1; // 已领取
|
||||||
|
} else if (claimable) {
|
||||||
|
status = 0; // 可领取
|
||||||
|
} else {
|
||||||
|
status = 2; // 未达标
|
||||||
|
}
|
||||||
records.add({
|
records.add({
|
||||||
'type': 'referral',
|
'type': 'referral',
|
||||||
'title': '推广福利 - ${map['referredUsername'] ?? '用户'}',
|
'title': '推广福利 - $username (${milestoneVal}000)',
|
||||||
'amount': map['amount']?.toString() ?? '0.00',
|
'amount': '100.00',
|
||||||
'status': map['status'] ?? 0,
|
'status': status,
|
||||||
'time': map['claimTime'] ?? map['createTime'],
|
'time': ms['claimTime'] ?? ms['createTime'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有 milestone 但有 claimableCount,也生成记录
|
||||||
|
if (milestones.isEmpty && claimableCount > 0) {
|
||||||
|
records.add({
|
||||||
|
'type': 'referral',
|
||||||
|
'title': '推广福利 - $username',
|
||||||
|
'amount': '${claimableCount * 100}',
|
||||||
|
'status': 0,
|
||||||
|
'time': null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,7 +382,7 @@ class _BillsPageState extends State<BillsPage> with SingleTickerProviderStateMix
|
|||||||
final amount = double.tryParse(record['amount']?.toString() ?? '0') ?? 0;
|
final amount = double.tryParse(record['amount']?.toString() ?? '0') ?? 0;
|
||||||
final status = record['status'] as int? ?? 0;
|
final status = record['status'] as int? ?? 0;
|
||||||
|
|
||||||
// status: 0=待领取, 1=已领取, 2=已过期
|
// status: 0=待领取, 1=已领取, 2=未达标
|
||||||
String statusText;
|
String statusText;
|
||||||
Color statusColor;
|
Color statusColor;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -349,7 +391,7 @@ class _BillsPageState extends State<BillsPage> with SingleTickerProviderStateMix
|
|||||||
statusColor = context.appColors.up;
|
statusColor = context.appColors.up;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
statusText = '已过期';
|
statusText = '未达标';
|
||||||
statusColor = colorScheme.onSurfaceVariant;
|
statusColor = colorScheme.onSurfaceVariant;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -355,6 +355,19 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
|||||||
final referralRewards =
|
final referralRewards =
|
||||||
_welfareData?['referralRewards'] as List<dynamic>? ?? [];
|
_welfareData?['referralRewards'] as List<dynamic>? ?? [];
|
||||||
|
|
||||||
|
// 汇总统计
|
||||||
|
int totalEarned = 0;
|
||||||
|
int totalClaimable = 0;
|
||||||
|
for (var r in referralRewards) {
|
||||||
|
final map = r as Map<String, dynamic>;
|
||||||
|
final milestones = map['milestones'] as List<dynamic>? ?? [];
|
||||||
|
for (var m in milestones) {
|
||||||
|
final ms = m as Map<String, dynamic>;
|
||||||
|
if (ms['claimed'] as bool? ?? false) totalEarned++;
|
||||||
|
if (ms['claimable'] as bool? ?? false) totalClaimable++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -370,6 +383,29 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
|||||||
color: context.appColors.onSurfaceMuted,
|
color: context.appColors.onSurfaceMuted,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// 汇总统计
|
||||||
|
if (referralRewards.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: context.appColors.surfaceCard,
|
||||||
|
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||||
|
border: Border.all(color: context.appColors.ghostBorder),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
_buildStatItem('已邀请', '${referralRewards.length}人'),
|
||||||
|
Container(width: 1, height: 20, color: context.appColors.ghostBorder),
|
||||||
|
_buildStatItem('已获得', '${totalEarned * 100} USDT'),
|
||||||
|
if (totalClaimable > 0) ...[
|
||||||
|
Container(width: 1, height: 20, color: context.appColors.ghostBorder),
|
||||||
|
_buildStatItem('待领取', '$totalClaimable个', highlight: true),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
|
|
||||||
// 推广列表卡片
|
// 推广列表卡片
|
||||||
@@ -384,6 +420,23 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildStatItem(String label, String value, {bool highlight = false}) {
|
||||||
|
return Expanded(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(label, style: AppTextStyles.bodySmall(context).copyWith(
|
||||||
|
color: context.colors.onSurfaceVariant,
|
||||||
|
)),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(value, style: AppTextStyles.headlineSmall(context).copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: highlight ? context.appColors.up : context.colors.onSurface,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildEmptyReferralList(BuildContext context) {
|
Widget _buildEmptyReferralList(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(32),
|
padding: const EdgeInsets.all(32),
|
||||||
@@ -416,6 +469,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
|||||||
final totalDeposit = data['totalDeposit']?.toString() ?? '0';
|
final totalDeposit = data['totalDeposit']?.toString() ?? '0';
|
||||||
final claimableCount = data['claimableCount'] as int? ?? 0;
|
final claimableCount = data['claimableCount'] as int? ?? 0;
|
||||||
final milestones = data['milestones'] as List<dynamic>? ?? [];
|
final milestones = data['milestones'] as List<dynamic>? ?? [];
|
||||||
|
final userId = data['userId'] as int? ?? 0;
|
||||||
final isLast = index == referralRewards.length - 1;
|
final isLast = index == referralRewards.length - 1;
|
||||||
|
|
||||||
// 进度计算
|
// 进度计算
|
||||||
@@ -446,7 +500,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
|||||||
Text(
|
Text(
|
||||||
username,
|
username,
|
||||||
style: AppTextStyles.headlineSmall(context).copyWith(
|
style: AppTextStyles.headlineSmall(context).copyWith(
|
||||||
fontWeight: FontWeight.w500, // 添加 w500
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
@@ -472,6 +526,11 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// 里程碑详情
|
||||||
|
if (milestones.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
_buildMilestoneDetails(milestones, userId),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -487,6 +546,66 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 里程碑详情行 — 显示每个里程碑状态
|
||||||
|
Widget _buildMilestoneDetails(List<dynamic> milestones, int userId) {
|
||||||
|
final upColor = context.appColors.up;
|
||||||
|
|
||||||
|
return Wrap(
|
||||||
|
spacing: 6,
|
||||||
|
runSpacing: 6,
|
||||||
|
children: milestones.map((m) {
|
||||||
|
final ms = m as Map<String, dynamic>;
|
||||||
|
final milestoneVal = ms['milestone'] as int? ?? 1;
|
||||||
|
final earned = ms['earned'] as bool? ?? false;
|
||||||
|
final claimed = ms['claimed'] as bool? ?? false;
|
||||||
|
final claimable = ms['claimable'] as bool? ?? false;
|
||||||
|
final threshold = ms['threshold']?.toString() ?? '${milestoneVal * 1000}';
|
||||||
|
|
||||||
|
Color bgColor;
|
||||||
|
Color textColor;
|
||||||
|
String label;
|
||||||
|
|
||||||
|
if (claimed) {
|
||||||
|
bgColor = upColor.withValues(alpha: 0.1);
|
||||||
|
textColor = upColor;
|
||||||
|
label = '${threshold}✓';
|
||||||
|
} else if (claimable) {
|
||||||
|
bgColor = context.appColors.accentPrimary.withValues(alpha: 0.15);
|
||||||
|
textColor = context.appColors.accentPrimary;
|
||||||
|
label = '${threshold}🎁';
|
||||||
|
} else if (earned) {
|
||||||
|
bgColor = upColor.withValues(alpha: 0.06);
|
||||||
|
textColor = upColor;
|
||||||
|
label = '${threshold}';
|
||||||
|
} else {
|
||||||
|
bgColor = context.appColors.surfaceCardHigh;
|
||||||
|
textColor = context.colors.onSurfaceVariant;
|
||||||
|
label = '${threshold}';
|
||||||
|
}
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: claimable ? () => _claimReferralBonus(userId, milestoneVal) : null,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: bgColor,
|
||||||
|
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||||
|
border: claimable ? Border.all(color: textColor.withValues(alpha: 0.3)) : null,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
style: AppTextStyles.bodySmall(context).copyWith(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: textColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildAvatar(String username) {
|
Widget _buildAvatar(String username) {
|
||||||
return Container(
|
return Container(
|
||||||
width: 32,
|
width: 32,
|
||||||
|
|||||||
Reference in New Issue
Block a user