111
This commit is contained in:
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import '../../../../core/theme/app_spacing.dart';
|
||||
import '../../../../core/theme/app_theme.dart';
|
||||
|
||||
/// 信息行组件(用于关于对话框)
|
||||
/// 信息行組件(用於關於對話框)
|
||||
class InfoRow extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String text;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 圆形头像组件
|
||||
/// 圓形頭像組件
|
||||
///
|
||||
/// 显示用户首字母或默认比特币符号。通过 [radius] 控制大小,
|
||||
/// [fontSize] 控制文字大小,[text] 可传入用户头像文字。
|
||||
/// 顯示用戶首字母或默認比特幣符號。通過 [radius] 控制大小,
|
||||
/// [fontSize] 控制文字大小,[text] 可傳入用戶頭像文字。
|
||||
class AvatarCircle extends StatelessWidget {
|
||||
final double radius;
|
||||
final double fontSize;
|
||||
|
||||
@@ -3,7 +3,7 @@ import '../../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../../core/theme/app_spacing.dart';
|
||||
import '../../../../core/theme/app_theme.dart';
|
||||
|
||||
/// 退出登录按钮
|
||||
/// 退出登錄按鈕
|
||||
class LogoutButton extends StatelessWidget {
|
||||
final VoidCallback onLogout;
|
||||
const LogoutButton({super.key, required this.onLogout});
|
||||
@@ -24,7 +24,7 @@ class LogoutButton extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'退出登录',
|
||||
'退出登錄',
|
||||
style: AppTextStyles.headlineMedium(context).copyWith(
|
||||
color: AppColorScheme.down,
|
||||
),
|
||||
|
||||
@@ -10,7 +10,7 @@ import 'menu_group_container.dart';
|
||||
import 'menu_row.dart';
|
||||
import 'menu_trailing_widgets.dart';
|
||||
|
||||
/// 菜单分组1 - 福利中心 / 实名认证 / 安全设置 / 消息通知
|
||||
/// 菜單分組1 - 福利中心 / 實名認證 / 安全設置 / 消息通知
|
||||
class MenuGroup1 extends StatelessWidget {
|
||||
final int kycStatus;
|
||||
final void Function(String) onShowComingSoon;
|
||||
@@ -39,11 +39,11 @@ class MenuGroup1 extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
// 实名认证
|
||||
// 實名認證
|
||||
MenuRow(
|
||||
icon: LucideIcons.shieldCheck,
|
||||
iconColor: context.appColors.up,
|
||||
title: '实名认证',
|
||||
title: '實名認證',
|
||||
trailing: KycBadge(kycStatus: kycStatus),
|
||||
onTap: () {
|
||||
if (kycStatus == 2) {
|
||||
@@ -57,12 +57,12 @@ class MenuGroup1 extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
// 安全设置
|
||||
// 安全設置
|
||||
MenuRow(
|
||||
icon: LucideIcons.lock,
|
||||
iconColor: context.colors.onSurfaceVariant,
|
||||
title: '安全设置',
|
||||
onTap: () => onShowComingSoon('安全设置'),
|
||||
title: '安全設置',
|
||||
onTap: () => onShowComingSoon('安全設置'),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
// 消息通知
|
||||
@@ -79,7 +79,7 @@ class MenuGroup1 extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 显示 KYC 认证状态对话框
|
||||
/// 顯示 KYC 認證狀態對話框
|
||||
void showKycStatusDialog(BuildContext context) {
|
||||
showShadDialog(
|
||||
context: context,
|
||||
@@ -88,13 +88,13 @@ void showKycStatusDialog(BuildContext context) {
|
||||
children: [
|
||||
Icon(Icons.check_circle, color: AppColorScheme.up, size: 20),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
const Text('实名认证'),
|
||||
const Text('實名認證'),
|
||||
],
|
||||
),
|
||||
description: const Text('您的实名认证已通过'),
|
||||
description: const Text('您的實名認證已通過'),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('确定'),
|
||||
child: const Text('確定'),
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'menu_group_container.dart';
|
||||
import 'menu_row.dart';
|
||||
import 'menu_trailing_widgets.dart';
|
||||
|
||||
/// 菜单分组2 - 深色模式 / 系统设置 / 关于我们
|
||||
/// 菜單分組2 - 深色模式 / 系統設置 / 關於我們
|
||||
class MenuGroup2 extends StatelessWidget {
|
||||
final VoidCallback onShowAbout;
|
||||
|
||||
@@ -20,21 +20,21 @@ class MenuGroup2 extends StatelessWidget {
|
||||
// 深色模式
|
||||
const DarkModeRow(),
|
||||
const Divider(height: 1),
|
||||
// 系统设置
|
||||
// 系統設置
|
||||
MenuRow(
|
||||
icon: LucideIcons.settings,
|
||||
iconColor: colorScheme.onSurfaceVariant,
|
||||
title: '系统设置',
|
||||
title: '系統設置',
|
||||
onTap: () {
|
||||
// TODO: 系统设置
|
||||
// TODO: 系統設置
|
||||
},
|
||||
),
|
||||
const Divider(height: 1),
|
||||
// 关于我们
|
||||
// 關於我們
|
||||
MenuRow(
|
||||
icon: LucideIcons.info,
|
||||
iconColor: colorScheme.onSurfaceVariant,
|
||||
title: '关于我们',
|
||||
title: '關於我們',
|
||||
onTap: onShowAbout,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
|
||||
import '../../../../core/theme/app_spacing.dart';
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
|
||||
/// 菜单分组容器 - 统一的圆角卡片样式
|
||||
/// 菜單分組容器 - 統一的圓角卡片樣式
|
||||
///
|
||||
/// 所有菜单分组共享相同的容器样式:背景色、圆角、边框。
|
||||
/// 通过 [child] 传入菜单项 Column。
|
||||
/// 所有菜單分組共享相同的容器樣式:背景色、圓角、邊框。
|
||||
/// 通過 [child] 傳入菜單項 Column。
|
||||
class MenuGroupContainer extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ import '../../../../core/theme/app_spacing.dart';
|
||||
import '../../../../core/theme/app_theme.dart';
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
|
||||
/// 单行菜单项:图标 + 标题 + 尾部组件 (chevron)
|
||||
/// 單行菜單項:圖標 + 標題 + 尾部組件 (chevron)
|
||||
///
|
||||
/// 图标颜色 (通常是使用主题色)
|
||||
/// 圖標顏色 (通常是使用主題色)
|
||||
class MenuRow extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final Color iconColor;
|
||||
|
||||
@@ -7,12 +7,12 @@ import '../../../../core/theme/app_theme.dart';
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
import '../../../../providers/theme_provider.dart';
|
||||
|
||||
/// KYC 状态徽章 (e.g. "已认证" green badge + chevron)
|
||||
/// KYC 狀態徽章 (e.g. "已認證" green badge + chevron)
|
||||
///
|
||||
/// 根据 [kycStatus] 显示不同状态:
|
||||
/// - 2: 已认证(绿色)
|
||||
/// - 1: 审核中(橙色)
|
||||
/// - 其他: 仅显示 chevron
|
||||
/// 根據 [kycStatus] 顯示不同狀態:
|
||||
/// - 2: 已認證(綠色)
|
||||
/// - 1: 審核中(橙色)
|
||||
/// - 其他: 僅顯示 chevron
|
||||
class KycBadge extends StatelessWidget {
|
||||
final int kycStatus;
|
||||
const KycBadge({super.key, required this.kycStatus});
|
||||
@@ -32,7 +32,7 @@ class KycBadge extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: Text(
|
||||
'已认证',
|
||||
'已認證',
|
||||
style: AppTextStyles.labelMedium(context).copyWith(
|
||||
color: green,
|
||||
),
|
||||
@@ -59,7 +59,7 @@ class KycBadge extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: Text(
|
||||
'审核中',
|
||||
'審核中',
|
||||
style: AppTextStyles.labelMedium(context).copyWith(
|
||||
color: AppColorScheme.warning,
|
||||
),
|
||||
@@ -83,7 +83,7 @@ class KycBadge extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 红点指示器 - 消息通知 + chevron
|
||||
/// 紅點指示器 - 消息通知 + chevron
|
||||
class RedDotIndicator extends StatelessWidget {
|
||||
const RedDotIndicator({super.key});
|
||||
|
||||
@@ -111,7 +111,7 @@ class RedDotIndicator extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 深色模式切换行
|
||||
/// 深色模式切換行
|
||||
class DarkModeRow extends StatelessWidget {
|
||||
const DarkModeRow({super.key});
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import '../../../../core/theme/app_theme.dart';
|
||||
import '../../../../core/theme/app_theme_extension.dart';
|
||||
import 'avatar_circle.dart';
|
||||
|
||||
/// 用户资料卡片 - 头像 + 用户名 + 徽章 + chevron
|
||||
/// 用戶資料卡片 - 頭像 + 用戶名 + 徽章 + chevron
|
||||
class ProfileCard extends StatelessWidget {
|
||||
final dynamic user;
|
||||
const ProfileCard({super.key, required this.user});
|
||||
@@ -37,12 +37,12 @@ class ProfileCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
user?.username ?? '未登录',
|
||||
user?.username ?? '未登錄',
|
||||
style: AppTextStyles.headlineLarge(context),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'普通用户',
|
||||
'普通用戶',
|
||||
style: AppTextStyles.bodyMedium(context).copyWith(
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
|
||||
@@ -11,7 +11,7 @@ import '../../../providers/auth_provider.dart';
|
||||
import '../../components/glass_panel.dart';
|
||||
import '../../components/neon_glow.dart';
|
||||
|
||||
/// KYC 实名认证页面
|
||||
/// KYC 實名認證頁面
|
||||
class KycPage extends StatefulWidget {
|
||||
final bool returnToWithdraw;
|
||||
|
||||
@@ -64,7 +64,7 @@ class _KycPageState extends State<KycPage> {
|
||||
backgroundColor: colorScheme.surface.withOpacity(0.0),
|
||||
elevation: 0,
|
||||
title: Text(
|
||||
'实名认证',
|
||||
'實名認證',
|
||||
style: AppTextStyles.headlineLarge(context),
|
||||
),
|
||||
leading: IconButton(
|
||||
@@ -77,17 +77,17 @@ class _KycPageState extends State<KycPage> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 步骤指示器
|
||||
// 步驟指示器
|
||||
_buildStepIndicator(colorScheme),
|
||||
SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// 主表单区
|
||||
// 主表單區
|
||||
GlassPanel(
|
||||
padding: EdgeInsets.all(AppSpacing.lg),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 标题区
|
||||
// 標題區
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
@@ -107,12 +107,12 @@ class _KycPageState extends State<KycPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'身份验证',
|
||||
'身份驗證',
|
||||
style: AppTextStyles.headlineLarge(context),
|
||||
),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
'上传身份证正反面完成实名认证',
|
||||
'上傳身份證正反面完成實名認證',
|
||||
style: AppTextStyles.bodyMedium(context),
|
||||
),
|
||||
],
|
||||
@@ -121,9 +121,9 @@ class _KycPageState extends State<KycPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// 身份证正面上传区
|
||||
// 身份證正面上傳區
|
||||
Text(
|
||||
'身份证正面(人像面)',
|
||||
'身份證正面(人像面)',
|
||||
style: AppTextStyles.headlineSmall(context),
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
@@ -136,26 +136,26 @@ class _KycPageState extends State<KycPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
|
||||
// 身份证反面上传区
|
||||
// 身份證反面上傳區
|
||||
Text(
|
||||
'身份证反面(国徽面)',
|
||||
'身份證反面(國徽面)',
|
||||
style: AppTextStyles.headlineSmall(context),
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
_buildUploadZone(
|
||||
imageFile: _backFile,
|
||||
imageBytes: _backBytes,
|
||||
label: '国徽面',
|
||||
label: '國徽面',
|
||||
onTap: () => _pickImage(false),
|
||||
colorScheme: colorScheme,
|
||||
),
|
||||
SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// 提交按钮
|
||||
// 提交按鈕
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: NeonButton(
|
||||
text: _isSubmitting ? '提交中...' : '提交认证',
|
||||
text: _isSubmitting ? '提交中...' : '提交認證',
|
||||
type: NeonButtonType.primary,
|
||||
onPressed: _canSubmit ? _submitKyc : null,
|
||||
height: 48,
|
||||
@@ -187,7 +187,7 @@ class _KycPageState extends State<KycPage> {
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'您的身份信息将被加密存储,仅用于身份验证',
|
||||
'您的身份信息將被加密存儲,僅用於身份驗證',
|
||||
style: AppTextStyles.bodySmall(context).copyWith(
|
||||
color: AppColorScheme.up.withOpacity(0.8),
|
||||
),
|
||||
@@ -209,7 +209,7 @@ class _KycPageState extends State<KycPage> {
|
||||
children: [
|
||||
_buildStepCircle(
|
||||
number: '1',
|
||||
label: '上传证件',
|
||||
label: '上傳證件',
|
||||
isActive: true,
|
||||
isComplete: isComplete,
|
||||
colorScheme: colorScheme,
|
||||
@@ -224,7 +224,7 @@ class _KycPageState extends State<KycPage> {
|
||||
),
|
||||
_buildStepCircle(
|
||||
number: '2',
|
||||
label: '认证完成',
|
||||
label: '認證完成',
|
||||
isActive: false,
|
||||
isComplete: false,
|
||||
colorScheme: colorScheme,
|
||||
@@ -317,12 +317,12 @@ class _KycPageState extends State<KycPage> {
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
// 图片预览 - 使用 memory 以兼容 Web
|
||||
// 圖片預覽 - 使用 memory 以兼容 Web
|
||||
Image.memory(
|
||||
imageBytes!,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
// 底部渐变遮罩 + 文字
|
||||
// 底部漸變遮罩 + 文字
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
@@ -348,7 +348,7 @@ class _KycPageState extends State<KycPage> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'$label已选择',
|
||||
'$label已選擇',
|
||||
style: AppTextStyles.labelLarge(context).copyWith(
|
||||
color: colorScheme.onPrimary,
|
||||
),
|
||||
@@ -400,7 +400,7 @@ class _KycPageState extends State<KycPage> {
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
'点击上传$label',
|
||||
'點擊上傳$label',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
color: colorScheme.onSurfaceVariant.withOpacity(0.6),
|
||||
),
|
||||
@@ -442,13 +442,13 @@ class _KycPageState extends State<KycPage> {
|
||||
size: 20,
|
||||
),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
const Text('认证成功'),
|
||||
const Text('認證成功'),
|
||||
],
|
||||
),
|
||||
description: const Text('您的实名认证已通过,现在可以进行提现操作'),
|
||||
description: const Text('您的實名認證已通過,現在可以進行提現操作'),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('确定'),
|
||||
child: const Text('確定'),
|
||||
onPressed: () {
|
||||
Navigator.of(ctx).pop();
|
||||
Navigator.of(context).pop();
|
||||
@@ -461,11 +461,11 @@ class _KycPageState extends State<KycPage> {
|
||||
showShadDialog(
|
||||
context: context,
|
||||
builder: (ctx) => ShadDialog.alert(
|
||||
title: const Text('认证失败'),
|
||||
description: Text(response.message ?? '请稍后重试'),
|
||||
title: const Text('認證失敗'),
|
||||
description: Text(response.message ?? '請稍後重試'),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('确定'),
|
||||
child: const Text('確定'),
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
),
|
||||
],
|
||||
@@ -477,11 +477,11 @@ class _KycPageState extends State<KycPage> {
|
||||
showShadDialog(
|
||||
context: context,
|
||||
builder: (ctx) => ShadDialog.alert(
|
||||
title: const Text('认证失败'),
|
||||
title: const Text('認證失敗'),
|
||||
description: Text(e.toString()),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('确定'),
|
||||
child: const Text('確定'),
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
),
|
||||
],
|
||||
@@ -494,7 +494,7 @@ class _KycPageState extends State<KycPage> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 虚线边框画笔
|
||||
/// 虛線邊框畫筆
|
||||
class _DashedBorderPainter extends CustomPainter {
|
||||
final Color color;
|
||||
final double borderRadius;
|
||||
|
||||
@@ -13,7 +13,7 @@ import 'components/menu_group1.dart';
|
||||
import 'components/menu_group2.dart';
|
||||
import 'components/profile_card.dart';
|
||||
|
||||
/// 我的页面 - 匹配 .pen 设计稿
|
||||
/// 我的頁面 - 匹配 .pen 設計稿
|
||||
class MinePage extends StatefulWidget {
|
||||
const MinePage({super.key});
|
||||
|
||||
@@ -77,10 +77,10 @@ class _MinePageState extends State<MinePage>
|
||||
children: [
|
||||
Icon(Icons.construction, color: AppColorScheme.warning, size: 20),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
const Text('功能开发中'),
|
||||
const Text('功能開發中'),
|
||||
],
|
||||
),
|
||||
description: Text('$feature功能正在开发中,敬请期待~'),
|
||||
description: Text('$feature功能正在開發中,敬請期待~'),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('知道了'),
|
||||
@@ -100,7 +100,7 @@ class _MinePageState extends State<MinePage>
|
||||
children: [
|
||||
AvatarCircle(radius: 20, fontSize: 16),
|
||||
SizedBox(width: AppSpacing.sm + AppSpacing.xs),
|
||||
const Text('模拟所'),
|
||||
const Text('模擬所'),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
@@ -108,7 +108,7 @@ class _MinePageState extends State<MinePage>
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'虚拟货币模拟交易平台',
|
||||
'虛擬貨幣模擬交易平臺',
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
SizedBox(height: AppSpacing.md),
|
||||
@@ -121,7 +121,7 @@ class _MinePageState extends State<MinePage>
|
||||
),
|
||||
actions: [
|
||||
ShadButton(
|
||||
child: const Text('确定'),
|
||||
child: const Text('確定'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
@@ -133,8 +133,8 @@ class _MinePageState extends State<MinePage>
|
||||
showShadDialog(
|
||||
context: context,
|
||||
builder: (ctx) => ShadDialog.alert(
|
||||
title: const Text('确认退出'),
|
||||
description: const Text('确定要退出登录吗?'),
|
||||
title: const Text('確認退出'),
|
||||
description: const Text('確定要退出登錄嗎?'),
|
||||
actions: [
|
||||
ShadButton.outline(
|
||||
child: const Text('取消'),
|
||||
|
||||
@@ -11,7 +11,7 @@ import '../../../core/event/app_event_bus.dart';
|
||||
import '../../../data/services/bonus_service.dart';
|
||||
import '../../../providers/asset_provider.dart';
|
||||
|
||||
/// 福利中心页面
|
||||
/// 福利中心頁面
|
||||
class WelfareCenterPage extends StatefulWidget {
|
||||
const WelfareCenterPage({super.key});
|
||||
|
||||
@@ -45,10 +45,10 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 容器样式辅助
|
||||
// 容器樣式輔助
|
||||
// ============================================
|
||||
|
||||
/// 标准卡片容器
|
||||
/// 標準卡片容器
|
||||
BoxDecoration _cardDecoration({Color? borderColor}) {
|
||||
return BoxDecoration(
|
||||
color: context.appColors.surfaceCard,
|
||||
@@ -59,11 +59,11 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 金色渐变卡片容器
|
||||
/// 金色漸變卡片容器
|
||||
BoxDecoration _goldGradientDecoration() {
|
||||
final isDark = context.isDark;
|
||||
// Light Mode: 琥珀色渐变(从 amber 15% 到深灰 5%)
|
||||
// Dark Mode: 金色渐变
|
||||
// Light Mode: 琥珀色漸變(從 amber 15% 到深灰 5%)
|
||||
// Dark Mode: 金色漸變
|
||||
final gradientColors = isDark
|
||||
? [
|
||||
context.appColors.accentPrimary.withValues(alpha: 0.15),
|
||||
@@ -90,7 +90,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 状态胶囊标签
|
||||
/// 狀態膠囊標籤
|
||||
Widget _statusBadge(String text, Color textColor, Color bgColor) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6), // [4,10] → [6,14]
|
||||
@@ -105,7 +105,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 全宽按钮
|
||||
/// 全寬按鈕
|
||||
Widget _fullWidthButton({
|
||||
required String text,
|
||||
required Color backgroundColor,
|
||||
@@ -192,7 +192,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 推广码卡片(金色渐变边框 Hero Card)
|
||||
// 推廣碼卡片(金色漸變邊框 Hero Card)
|
||||
// ============================================
|
||||
|
||||
Widget _buildReferralCodeCard(BuildContext context) {
|
||||
@@ -206,13 +206,13 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header Row: gift icon + 标题
|
||||
// Header Row: gift icon + 標題
|
||||
Row(
|
||||
children: [
|
||||
Icon(LucideIcons.gift, color: goldAccent, size: 24),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
'我的邀请码',
|
||||
'我的邀請碼',
|
||||
style: AppTextStyles.headlineLarge(context).copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
@@ -221,9 +221,9 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
referralCode.isEmpty ? '暂无邀请码' : referralCode,
|
||||
referralCode.isEmpty ? '暫無邀請碼' : referralCode,
|
||||
style: AppTextStyles.displayMedium(context).copyWith(
|
||||
fontSize: 24, // 明确设置为 24px
|
||||
fontSize: 24, // 明確設置為 24px
|
||||
fontWeight: FontWeight.w800,
|
||||
color: goldAccent,
|
||||
letterSpacing: 2,
|
||||
@@ -238,7 +238,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
? null
|
||||
: () {
|
||||
Clipboard.setData(ClipboardData(text: referralCode));
|
||||
ToastUtils.show('邀请码已复制');
|
||||
ToastUtils.show('邀請碼已複製');
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: goldAccent,
|
||||
@@ -250,7 +250,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
disabledBackgroundColor: goldAccent.withValues(alpha: 0.4),
|
||||
),
|
||||
child: Text(
|
||||
'复制邀请码',
|
||||
'複製邀請碼',
|
||||
style: AppTextStyles.headlineMedium(context).copyWith(color: context.colors.onPrimary),
|
||||
),
|
||||
),
|
||||
@@ -272,7 +272,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
final claimed = newUserBonus?['claimed'] as bool? ?? false;
|
||||
final deposited = newUserBonus?['deposited'] as bool? ?? false;
|
||||
|
||||
// 状态判定
|
||||
// 狀態判定
|
||||
String badgeText;
|
||||
bool showAvailableBadge;
|
||||
String buttonText;
|
||||
@@ -280,23 +280,23 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
String description;
|
||||
|
||||
if (claimed) {
|
||||
badgeText = '已领取';
|
||||
badgeText = '已領取';
|
||||
showAvailableBadge = false;
|
||||
buttonText = '已领取';
|
||||
buttonText = '已領取';
|
||||
canClaim = false;
|
||||
description = '新人福利已领取';
|
||||
description = '新人福利已領取';
|
||||
} else if (eligible) {
|
||||
badgeText = '可领取';
|
||||
badgeText = '可領取';
|
||||
showAvailableBadge = true;
|
||||
buttonText = '立即领取';
|
||||
buttonText = '立即領取';
|
||||
canClaim = true;
|
||||
description = '完成首次充值即可领取';
|
||||
description = '完成首次充值即可領取';
|
||||
} else {
|
||||
badgeText = deposited ? '已充值' : '待解锁';
|
||||
badgeText = deposited ? '已充值' : '待解鎖';
|
||||
showAvailableBadge = false;
|
||||
buttonText = '未解锁';
|
||||
buttonText = '未解鎖';
|
||||
canClaim = false;
|
||||
description = deposited ? '已充值,等待系统确认' : '完成首次充值即可领取';
|
||||
description = deposited ? '已充值,等待系統確認' : '完成首次充值即可領取';
|
||||
}
|
||||
|
||||
return Container(
|
||||
@@ -306,7 +306,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header: 标题 + 状态标签
|
||||
// Header: 標題 + 狀態標籤
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@@ -348,14 +348,14 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 推广奖励列表
|
||||
// 推廣獎勵列表
|
||||
// ============================================
|
||||
|
||||
Widget _buildReferralRewardsSection(BuildContext context) {
|
||||
final referralRewards =
|
||||
_welfareData?['referralRewards'] as List<dynamic>? ?? [];
|
||||
|
||||
// 汇总统计
|
||||
// 彙總統計
|
||||
int totalEarned = 0;
|
||||
int totalClaimable = 0;
|
||||
for (var r in referralRewards) {
|
||||
@@ -373,17 +373,17 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
children: [
|
||||
// Section Header
|
||||
Text(
|
||||
'推广奖励',
|
||||
'推廣獎勵',
|
||||
style: AppTextStyles.headlineLarge(context),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'每邀请一位好友充值达标,奖励100 USDT',
|
||||
'每邀請一位好友充值達標,獎勵100 USDT',
|
||||
style: AppTextStyles.bodySmall(context).copyWith(
|
||||
color: context.appColors.onSurfaceMuted,
|
||||
),
|
||||
),
|
||||
// 汇总统计
|
||||
// 彙總統計
|
||||
if (referralRewards.isNotEmpty) ...[
|
||||
const SizedBox(height: 12),
|
||||
Container(
|
||||
@@ -395,12 +395,12 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
_buildStatItem('已邀请', '${referralRewards.length}人'),
|
||||
_buildStatItem('已邀請', '${referralRewards.length}人'),
|
||||
Container(width: 1, height: 20, color: context.appColors.ghostBorder),
|
||||
_buildStatItem('已获得', '${totalEarned * 100} USDT'),
|
||||
_buildStatItem('已獲得', '${totalEarned * 100} USDT'),
|
||||
if (totalClaimable > 0) ...[
|
||||
Container(width: 1, height: 20, color: context.appColors.ghostBorder),
|
||||
_buildStatItem('待领取', '$totalClaimable个', highlight: true),
|
||||
_buildStatItem('待領取', '$totalClaimable個', highlight: true),
|
||||
],
|
||||
],
|
||||
),
|
||||
@@ -408,7 +408,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// 推广列表卡片
|
||||
// 推廣列表卡片
|
||||
Container(
|
||||
width: double.infinity,
|
||||
decoration: _cardDecoration(),
|
||||
@@ -450,7 +450,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'暂无推广用户',
|
||||
'暫無推廣用戶',
|
||||
style: AppTextStyles.bodyLarge(context).copyWith(
|
||||
color: context.colors.onSurfaceVariant,
|
||||
),
|
||||
@@ -470,18 +470,21 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
final claimableCount = data['claimableCount'] as int? ?? 0;
|
||||
final milestones = data['milestones'] as List<dynamic>? ?? [];
|
||||
final userId = data['userId'] as int? ?? 0;
|
||||
final indirectRefCount = data['indirectRefCount'] as int? ?? 0;
|
||||
final indirectClaimableCount = data['indirectClaimableCount'] as int? ?? 0;
|
||||
final indirectMilestones = data['indirectMilestones'] as List<dynamic>? ?? [];
|
||||
final isLast = index == referralRewards.length - 1;
|
||||
|
||||
// 进度计算
|
||||
// 進度計算
|
||||
final progress = _computeProgress(milestones, totalDeposit);
|
||||
// 操作按钮
|
||||
// 操作按鈕
|
||||
final actionWidget = _buildReferralAction(
|
||||
data: data,
|
||||
claimableCount: claimableCount,
|
||||
milestones: milestones,
|
||||
progress: progress,
|
||||
);
|
||||
// 进度条颜色
|
||||
// 進度條顏色
|
||||
final progressColor = _referralProgressColor(claimableCount, progress);
|
||||
|
||||
return Column(
|
||||
@@ -526,11 +529,21 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
// 里程碑详情
|
||||
// 里程碑詳情
|
||||
if (milestones.isNotEmpty) ...[
|
||||
const SizedBox(height: 12),
|
||||
_buildMilestoneDetails(milestones, userId),
|
||||
],
|
||||
// 間接推廣獎勵
|
||||
if (indirectRefCount > 0) ...[
|
||||
const SizedBox(height: 12),
|
||||
_buildIndirectSection(
|
||||
userId,
|
||||
indirectRefCount,
|
||||
indirectClaimableCount,
|
||||
indirectMilestones,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -546,7 +559,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 里程碑详情行 — 显示每个里程碑状态
|
||||
/// 里程碑詳情行 — 顯示每個里程碑狀態
|
||||
Widget _buildMilestoneDetails(List<dynamic> milestones, int userId) {
|
||||
final upColor = context.appColors.up;
|
||||
|
||||
@@ -625,7 +638,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 计算推荐奖励进度
|
||||
/// 計算推薦獎勵進度
|
||||
double _computeProgress(List<dynamic> milestones, String totalDeposit) {
|
||||
if (milestones.isNotEmpty) {
|
||||
int earnedCount = milestones.where((m) {
|
||||
@@ -638,14 +651,14 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
return (deposit / 1000).clamp(0.0, 1.0);
|
||||
}
|
||||
|
||||
/// 根据状态获取进度条颜色
|
||||
/// 根據狀態獲取進度條顏色
|
||||
Color _referralProgressColor(int claimableCount, double progress) {
|
||||
if (claimableCount > 0) return context.appColors.up;
|
||||
if (progress > 0) return context.appColors.accentPrimary;
|
||||
return context.appColors.surfaceCardHigh;
|
||||
}
|
||||
|
||||
/// 构建推荐奖励的操作按钮
|
||||
/// 構建推薦獎勵的操作按鈕
|
||||
Widget? _buildReferralAction({
|
||||
required Map<String, dynamic> data,
|
||||
required int claimableCount,
|
||||
@@ -665,21 +678,136 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => _claimReferralBonus(data['userId'] as int, milestoneValue),
|
||||
child: _statusBadge('领取', profitGreen, profitGreenBg),
|
||||
child: _statusBadge('領取', profitGreen, profitGreenBg),
|
||||
);
|
||||
}
|
||||
if (progress > 0) {
|
||||
final warningColor = AppColorScheme.warning;
|
||||
return _statusBadge('进行中', warningColor, warningColor.withValues(alpha: 0.15));
|
||||
return _statusBadge('進行中', warningColor, warningColor.withValues(alpha: 0.15));
|
||||
}
|
||||
return Text(
|
||||
'待达标',
|
||||
'待達標',
|
||||
style: AppTextStyles.labelLarge(context).copyWith(color: context.appColors.onSurfaceMuted),
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 奖励规则卡片
|
||||
// 間接推廣獎勵區塊
|
||||
// ============================================
|
||||
|
||||
Widget _buildIndirectSection(
|
||||
int directReferralId,
|
||||
int indirectRefCount,
|
||||
int indirectClaimableCount,
|
||||
List<dynamic> indirectMilestones,
|
||||
) {
|
||||
final goldAccent = context.appColors.accentPrimary;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: context.appColors.surfaceCardHigh.withValues(alpha: 0.5),
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(LucideIcons.users, size: 14, color: goldAccent),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'已推廣 $indirectRefCount 人',
|
||||
style: AppTextStyles.bodyMedium(context).copyWith(
|
||||
color: context.colors.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
if (indirectClaimableCount > 0) ...[
|
||||
const Spacer(),
|
||||
_statusBadge(
|
||||
'$indirectClaimableCount 個可領',
|
||||
context.appColors.up,
|
||||
context.appColors.upBackground,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
// 間接里程碑標籤
|
||||
if (indirectMilestones.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
_buildIndirectMilestoneTags(directReferralId, indirectMilestones),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildIndirectMilestoneTags(int directReferralId, List<dynamic> milestones) {
|
||||
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 indirectReferredUserId = ms['indirectReferredUserId'] as int? ?? 0;
|
||||
|
||||
// 不顯示未達標的里程碑
|
||||
if (!earned && !claimed) return const SizedBox.shrink();
|
||||
|
||||
Color bgColor;
|
||||
Color textColor;
|
||||
String label;
|
||||
|
||||
if (claimed) {
|
||||
bgColor = upColor.withValues(alpha: 0.1);
|
||||
textColor = upColor;
|
||||
label = '50\u2713';
|
||||
} else if (claimable) {
|
||||
bgColor = context.appColors.accentPrimary.withValues(alpha: 0.15);
|
||||
textColor = context.appColors.accentPrimary;
|
||||
label = '50\u{1F381}';
|
||||
} else {
|
||||
bgColor = context.appColors.surfaceCardHigh;
|
||||
textColor = context.colors.onSurfaceVariant;
|
||||
label = '50';
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: claimable
|
||||
? () => _claimIndirectReferralBonus(
|
||||
directReferralId,
|
||||
indirectReferredUserId,
|
||||
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 _buildRulesCard(BuildContext context) {
|
||||
@@ -694,13 +822,14 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'奖励规则',
|
||||
'獎勵規則',
|
||||
style: AppTextStyles.headlineSmall(context),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_buildRuleItem('新用户注册完成实名认证奖励 100 USDT'),
|
||||
_buildRuleItem('邀请好友充值每达 1000 USDT,双方各获得 100 USDT'),
|
||||
_buildRuleItem('奖励直接发放至资金账户'),
|
||||
_buildRuleItem('新用戶註冊完成實名認證獎勵 100 USDT'),
|
||||
_buildRuleItem('邀請好友充值每達 1000 USDT,獎勵 100 USDT'),
|
||||
_buildRuleItem('好友推廣的人充值每達 1000 USDT,額外獎勵 50 USDT'),
|
||||
_buildRuleItem('獎勵直接發放至資金賬戶'),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -719,7 +848,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 业务逻辑
|
||||
// 業務邏輯
|
||||
// ============================================
|
||||
|
||||
Future<void> _claimNewUserBonus() async {
|
||||
@@ -731,13 +860,13 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
if (response.success) {
|
||||
context.read<AssetProvider>().refreshAll(force: true);
|
||||
context.read<AppEventBus>().fire(AppEventType.assetChanged);
|
||||
ToastUtils.show('领取成功!100 USDT 已到账');
|
||||
ToastUtils.show('領取成功!100 USDT 已到賬');
|
||||
_loadData();
|
||||
} else {
|
||||
ToastUtils.show(response.message ?? '领取失败');
|
||||
ToastUtils.show(response.message ?? '領取失敗');
|
||||
}
|
||||
} catch (e) {
|
||||
ToastUtils.show('领取失败: $e');
|
||||
ToastUtils.show('領取失敗: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,13 +882,40 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
|
||||
if (response.success) {
|
||||
context.read<AssetProvider>().refreshAll(force: true);
|
||||
context.read<AppEventBus>().fire(AppEventType.assetChanged);
|
||||
ToastUtils.show('领取成功!100 USDT 已到账');
|
||||
ToastUtils.show('領取成功!100 USDT 已到賬');
|
||||
_loadData();
|
||||
} else {
|
||||
ToastUtils.show(response.message ?? '领取失败');
|
||||
ToastUtils.show(response.message ?? '領取失敗');
|
||||
}
|
||||
} catch (e) {
|
||||
ToastUtils.show('领取失败: $e');
|
||||
ToastUtils.show('領取失敗: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _claimIndirectReferralBonus(
|
||||
int directReferralId,
|
||||
int indirectReferredUserId,
|
||||
int milestone,
|
||||
) async {
|
||||
try {
|
||||
final bonusService = context.read<BonusService>();
|
||||
final response = await bonusService.claimIndirectReferralBonus(
|
||||
directReferralId,
|
||||
indirectReferredUserId,
|
||||
milestone,
|
||||
);
|
||||
if (!mounted) return;
|
||||
|
||||
if (response.success) {
|
||||
context.read<AssetProvider>().refreshAll(force: true);
|
||||
context.read<AppEventBus>().fire(AppEventType.assetChanged);
|
||||
ToastUtils.show('領取成功!50 USDT 已到賬');
|
||||
_loadData();
|
||||
} else {
|
||||
ToastUtils.show(response.message ?? '領取失敗');
|
||||
}
|
||||
} catch (e) {
|
||||
ToastUtils.show('領取失敗: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user