docs: 删除过时的功能规格文档

feat(ui): 重构资产页面UI,移除shadcn_ui依赖并简化设计

- 删除三个过时的功能规格文档(apply-new-styles.md、bottom-nav-labels.md、theme-dynamic-colors.md)
- 重构充值页面(deposit_page.dart):移除shadcn_ui依赖,简化表单验证和UI设计,使用动态主题颜色
- 重构划转页面(transfer_page.dart):移除复杂动画和shadcn_ui依赖,简化UI布局和交互逻辑
- 重构提现页面(withdraw_page.dart):移除shadcn_ui依赖,简化表单验证和网络选择器
- 重构我的页面相关组件:统一使用动态主题颜色,简化菜单项设计和KYC状态显示
- 所有页面现在使用Theme.of(context)获取动态颜色,支持明暗主题切换
- 移除硬编码的颜色引用,提高代码可维护性和主题一致性
This commit is contained in:
2026-04-08 01:47:51 +08:00
parent 007915b6f2
commit dc6a8afc9a
13 changed files with 1271 additions and 2074 deletions

View File

@@ -1,34 +1,29 @@
import 'package:flutter/material.dart';
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});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onLogout,
child: Container(
width: double.infinity,
height: 48,
decoration: BoxDecoration(
color: AppColorScheme.down.withOpacity(0.05),
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: AppColorScheme.down.withOpacity(0.15),
final colorScheme = Theme.of(context).colorScheme;
return SizedBox(
width: double.infinity,
height: 48,
child: OutlinedButton(
onPressed: onLogout,
style: OutlinedButton.styleFrom(
foregroundColor: colorScheme.error,
side: BorderSide(color: colorScheme.error),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(14),
),
),
child: Center(
child: Text(
'退出登錄',
style: AppTextStyles.headlineMedium(context).copyWith(
color: AppColorScheme.down,
),
),
child: const Text(
'退出登錄',
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500),
),
),
);

View File

@@ -1,16 +1,12 @@
import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import '../../../../core/theme/app_color_scheme.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../kyc_page.dart';
import '../welfare_center_page.dart';
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;
@@ -23,13 +19,14 @@ class MenuGroup1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return MenuGroupContainer(
child: Column(
children: [
// 福利中心
MenuRow(
icon: LucideIcons.gift,
iconColor: AppColorScheme.darkSecondary, // gold
iconColor: colorScheme.secondary,
title: '福利中心',
onTap: () {
Navigator.push(
@@ -39,15 +36,14 @@ class MenuGroup1 extends StatelessWidget {
},
),
const Divider(height: 1),
// 實名認證
MenuRow(
icon: LucideIcons.shieldCheck,
iconColor: context.appColors.up,
iconColor: colorScheme.secondary,
title: '實名認證',
trailing: KycBadge(kycStatus: kycStatus),
onTap: () {
if (kycStatus == 2) {
showKycStatusDialog(context);
_showKycStatusDialog(context);
} else {
Navigator.push(
context,
@@ -57,18 +53,16 @@ class MenuGroup1 extends StatelessWidget {
},
),
const Divider(height: 1),
// 安全設置
MenuRow(
icon: LucideIcons.lock,
iconColor: context.colors.onSurfaceVariant,
iconColor: colorScheme.onSurfaceVariant,
title: '安全設置',
onTap: () => onShowComingSoon('安全設置'),
),
const Divider(height: 1),
// 消息通知
MenuRow(
icon: LucideIcons.bell,
iconColor: context.colors.onSurfaceVariant,
iconColor: colorScheme.onSurfaceVariant,
title: '消息通知',
trailing: const RedDotIndicator(),
onTap: () => onShowComingSoon('消息通知'),
@@ -79,23 +73,16 @@ class MenuGroup1 extends StatelessWidget {
}
}
/// 顯示 KYC 認證狀態對話框
void showKycStatusDialog(BuildContext context) {
showShadDialog(
void _showKycStatusDialog(BuildContext context) {
showDialog(
context: context,
builder: (ctx) => ShadDialog.alert(
title: Row(
children: [
Icon(Icons.check_circle, color: AppColorScheme.up, size: 20),
SizedBox(width: AppSpacing.sm),
const Text('實名認證'),
],
),
description: const Text('您的實名認證已通過'),
builder: (ctx) => AlertDialog(
title: const Text('實名認證'),
content: const Text('您的實名認證已通過'),
actions: [
ShadButton(
child: const Text('確定'),
TextButton(
onPressed: () => Navigator.of(ctx).pop(),
child: const Text('确定'),
),
],
),

View File

@@ -1,11 +1,6 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme_extension.dart';
/// 菜單分組容器 - 統一的圓角卡片樣式
///
/// 所有菜單分組共享相同的容器樣式:背景色、圓角、邊框。
/// 通過 [child] 傳入菜單項 Column。
/// 菜单分组容器
class MenuGroupContainer extends StatelessWidget {
final Widget child;
@@ -13,14 +8,16 @@ class MenuGroupContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
width: double.infinity,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
color: colorScheme.surface,
borderRadius: BorderRadius.circular(14),
border: Border.all(
color: context.appColors.ghostBorder,
color: colorScheme.outlineVariant.withValues(alpha: 0.5),
),
),
child: child,

View File

@@ -1,12 +1,8 @@
import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
/// 行菜單項:圖標 + 標題 + 尾部組件 (chevron)
///
/// 圖標顏色 (通常是使用主題色)
/// 行菜单项:图标 + 标题 + 尾部
class MenuRow extends StatelessWidget {
final IconData icon;
final Color iconColor;
@@ -25,38 +21,30 @@ class MenuRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Row(
children: [
// Icon in 36x36 rounded container
Container(
width: 36,
height: 36,
decoration: BoxDecoration(
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Icon(icon, size: 18, color: iconColor),
),
),
Icon(icon, size: 18, color: iconColor),
const SizedBox(width: 10),
// Title
Expanded(
child: Text(
title,
style: AppTextStyles.headlineMedium(context),
style: AppTextStyles.bodyLarge(context).copyWith(
fontWeight: FontWeight.w500,
),
),
),
// Trailing
if (trailing != null)
if (trailing != null) trailing!,
if (trailing == null)
Icon(
LucideIcons.chevronRight,
size: 16,
color: context.colors.onSurfaceVariant,
color: colorScheme.onSurfaceVariant,
),
],
),

View File

@@ -1,178 +1,96 @@
import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import 'package:provider/provider.dart';
import '../../../../core/theme/app_color_scheme.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../providers/theme_provider.dart';
/// KYC 狀態徽章 (e.g. "已認證" green badge + chevron)
///
/// 根據 [kycStatus] 顯示不同狀態:
/// - 2: 已認證(綠色)
/// - 1: 審核中(橙色)
/// - 其他: 僅顯示 chevron
/// KYC 状态文字
class KycBadge extends StatelessWidget {
final int kycStatus;
const KycBadge({super.key, required this.kycStatus});
@override
Widget build(BuildContext context) {
final green = context.appColors.up;
final colorScheme = Theme.of(context).colorScheme;
if (kycStatus == 2) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: green.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Text(
'已認證',
style: AppTextStyles.labelMedium(context).copyWith(
color: green,
),
),
),
const SizedBox(width: 8),
Icon(
LucideIcons.chevronRight,
size: 16,
color: context.colors.onSurfaceVariant,
),
],
return Text(
'已認證',
style: AppTextStyles.bodySmall(context).copyWith(
color: colorScheme.secondary,
fontWeight: FontWeight.w500,
),
);
}
if (kycStatus == 1) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: AppColorScheme.warning.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Text(
'審核中',
style: AppTextStyles.labelMedium(context).copyWith(
color: AppColorScheme.warning,
),
),
),
const SizedBox(width: 8),
Icon(
LucideIcons.chevronRight,
size: 16,
color: context.colors.onSurfaceVariant,
),
],
return Text(
'審核中',
style: AppTextStyles.bodySmall(context).copyWith(
color: colorScheme.tertiary,
fontWeight: FontWeight.w500,
),
);
}
return Icon(
LucideIcons.chevronRight,
size: 16,
color: context.colors.onSurfaceVariant,
return Text(
'未認證',
style: AppTextStyles.bodySmall(context).copyWith(
color: colorScheme.onSurfaceVariant,
),
);
}
}
/// 紅點指示器 - 消息通知 + chevron
/// 红点指示器
class RedDotIndicator extends StatelessWidget {
const RedDotIndicator({super.key});
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: AppColorScheme.down,
shape: BoxShape.circle,
),
),
const SizedBox(width: 8),
Icon(
LucideIcons.chevronRight,
size: 16,
color: context.colors.onSurfaceVariant,
),
],
final colorScheme = Theme.of(context).colorScheme;
return Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: colorScheme.error,
shape: BoxShape.circle,
),
);
}
}
/// 深色模式切
/// 深色模式切
class DarkModeRow extends StatelessWidget {
const DarkModeRow({super.key});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final themeProvider = context.watch<ThemeProvider>();
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Row(
children: [
// Icon in 36x36 rounded container
Container(
width: 36,
height: 36,
decoration: BoxDecoration(
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Icon(
LucideIcons.moon,
size: 18,
color: context.colors.onSurfaceVariant,
),
),
Icon(
LucideIcons.moon,
size: 18,
color: colorScheme.onSurfaceVariant,
),
const SizedBox(width: 10),
Expanded(
child: Text(
'深色模式',
style: AppTextStyles.headlineMedium(context),
),
),
// Toggle switch - matching .pen design (44x24 rounded pill)
GestureDetector(
onTap: () => themeProvider.toggleTheme(),
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
width: 44,
height: 24,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(12),
),
child: AnimatedAlign(
duration: const Duration(milliseconds: 200),
alignment:
themeProvider.isDarkMode
? Alignment.centerRight : Alignment.centerLeft,
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
color: context.colors.onSurface,
shape: BoxShape.circle,
),
style: AppTextStyles.bodyLarge(context).copyWith(
fontWeight: FontWeight.w500,
),
),
),
),
Switch(
value: themeProvider.isDarkMode,
onChanged: (_) => themeProvider.toggleTheme(),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
],
),

View File

@@ -1,60 +1,59 @@
import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import 'avatar_circle.dart';
/// 用戶資料卡片 - 頭像 + 用戶名 + 徽章 + chevron
/// 用户资料卡片
class ProfileCard extends StatelessWidget {
final dynamic user;
const ProfileCard({super.key, required this.user});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(20),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
color: colorScheme.surface,
borderRadius: BorderRadius.circular(14),
border: Border.all(
color: context.appColors.ghostBorder,
color: colorScheme.outlineVariant.withValues(alpha: 0.5),
),
),
child: Row(
children: [
// Avatar
AvatarCircle(
radius: 24,
fontSize: 18,
radius: 22,
fontSize: 16,
text: user?.avatarText,
),
const SizedBox(width: 12),
// Name + badge column
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
user?.username ?? '未登錄',
style: AppTextStyles.headlineLarge(context),
style: AppTextStyles.bodyLarge(context).copyWith(
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 4),
const SizedBox(height: 2),
Text(
'普通用戶',
style: AppTextStyles.bodyMedium(context).copyWith(
fontWeight: FontWeight.normal,
style: AppTextStyles.bodySmall(context).copyWith(
color: colorScheme.onSurfaceVariant,
),
),
],
),
),
// Chevron
Icon(
LucideIcons.chevronRight,
size: 16,
color: context.colors.onSurfaceVariant,
color: colorScheme.onSurfaceVariant,
),
],
),