refactor(theme): 迁移主题感知颜色至 ThemeExtension

- 创建 AppThemeColors ThemeExtension 类,统一管理主题感知颜色(涨跌色、卡片背景、渐变等)
- 从 AppColorScheme 移除主题感知辅助函数,仅保留静态颜色常量
- 在 AppTheme 中注册 ThemeExtension,支持深色/浅色主题工厂
- 重构所有 UI 组件使用 context.appColors 访问主题颜色,替代硬编码的 AppColorScheme 方法调用
- 移除组件中重复的 isDark 判断逻辑,简化颜色获取方式
- 保持向后兼容性,所有现有功能不变
This commit is contained in:
2026-04-06 01:58:08 +08:00
parent 396668aa43
commit 7ed2435a4c
36 changed files with 658 additions and 810 deletions

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../core/theme/app_spacing.dart';
/// 账户标签切换器 — .pen node UE6xC
@@ -19,14 +20,11 @@ class AccountTabSwitcher extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
height: 40,
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
color: isDark ? colorScheme.surfaceContainerHighest : colorScheme.surfaceContainerHigh,
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(AppRadius.md),
),
child: Row(
@@ -36,14 +34,12 @@ class AccountTabSwitcher extends StatelessWidget {
label: '资金账户',
isSelected: selectedIndex == 0,
onTap: () => onChanged(0),
isDark: isDark,
),
_buildTab(
context: context,
label: '交易账户',
isSelected: selectedIndex == 1,
onTap: () => onChanged(1),
isDark: isDark,
),
],
),
@@ -55,10 +51,7 @@ class AccountTabSwitcher extends StatelessWidget {
required String label,
required bool isSelected,
required VoidCallback onTap,
required bool isDark,
}) {
final colorScheme = Theme.of(context).colorScheme;
return Expanded(
child: GestureDetector(
onTap: onTap,
@@ -66,13 +59,13 @@ class AccountTabSwitcher extends StatelessWidget {
duration: const Duration(milliseconds: 200),
decoration: BoxDecoration(
color: isSelected
? colorScheme.surface
? context.colors.surface
: const Color(0x00000000),
borderRadius: BorderRadius.circular(AppRadius.sm),
boxShadow: isSelected
? [
BoxShadow(
color: colorScheme.shadow.withValues(alpha: 0.05),
color: context.colors.shadow.withValues(alpha: 0.05),
blurRadius: 3,
offset: const Offset(0, 1),
),
@@ -86,7 +79,7 @@ class AccountTabSwitcher extends StatelessWidget {
? AppTextStyles.headlineMedium(context)
: AppTextStyles.headlineMedium(context).copyWith(
fontWeight: FontWeight.w500,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
),

View File

@@ -2,6 +2,7 @@ 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';
/// 操作按钮行 — .pen node pIpHe
/// gap: 12, three buttons evenly distributed
@@ -22,10 +23,8 @@ class ActionButtonsRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final accentColor = isDark ? colorScheme.secondary : colorScheme.primary;
final bgColor = isDark ? colorScheme.surfaceContainerHighest : colorScheme.surfaceContainerHigh;
final accentColor = context.appColors.accentPrimary;
final bgColor = context.appColors.surfaceCardHigh;
return Row(
children: [

View File

@@ -4,6 +4,7 @@ import 'package:shadcn_ui/shadcn_ui.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import 'package:provider/provider.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../core/theme/app_color_scheme.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/utils/toast_utils.dart';
@@ -246,7 +247,6 @@ void showDepositResultDialog(BuildContext context, Map<String, dynamic> data) {
final walletAddress = data['walletAddress'] as String? ?? '';
final walletNetwork = data['walletNetwork'] as String? ?? 'TRC20';
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
showShadDialog(
context: context,
@@ -263,7 +263,7 @@ void showDepositResultDialog(BuildContext context, Map<String, dynamic> data) {
children: [
NeonIcon(
icon: Icons.check_circle,
color: AppColorScheme.getUpColor(isDark),
color: context.appColors.up,
size: 24,
),
const SizedBox(width: AppSpacing.sm),
@@ -361,7 +361,6 @@ void showWithdrawDialog(BuildContext context, String? balance) {
final contactController = TextEditingController();
final formKey = GlobalKey<ShadFormState>();
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
showShadDialog(
context: context,
@@ -412,10 +411,10 @@ void showWithdrawDialog(BuildContext context, String? balance) {
vertical: AppSpacing.sm,
),
decoration: BoxDecoration(
color: AppColorScheme.getUpBackgroundColor(isDark),
color: context.appColors.upBackground,
borderRadius: BorderRadius.circular(AppRadius.full),
border: Border.all(
color: AppColorScheme.getUpColor(isDark).withValues(alpha: 0.2),
color: context.appColors.up.withValues(alpha: 0.2),
),
),
child: Row(
@@ -431,7 +430,7 @@ void showWithdrawDialog(BuildContext context, String? balance) {
'$balance USDT',
style: AppTextStyles.labelLarge(context).copyWith(
fontWeight: FontWeight.bold,
color: AppColorScheme.getUpColor(isDark),
color: context.appColors.up,
),
),
],

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_color_scheme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../providers/asset_provider.dart';
import '../../../components/glass_panel.dart';
@@ -22,9 +22,6 @@ class BalanceCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final displayBalance = activeTab == 0
? (provider.fundAccount?.balance ?? provider.overview?.fundBalance ?? '0.00')
: _calculateTradeTotal();
@@ -38,7 +35,7 @@ class BalanceCard extends StatelessWidget {
Text(
'USDT 余额',
style: AppTextStyles.bodyMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
fontWeight: FontWeight.w400,
),
),
@@ -51,7 +48,7 @@ class BalanceCard extends StatelessWidget {
Text(
'\u2248 \$${_formatBalance(displayBalance)} USD',
style: AppTextStyles.bodyMedium(context).copyWith(
color: isDark ? AppColorScheme.darkOnSurfaceMuted : colorScheme.onSurfaceVariant,
color: context.appColors.onSurfaceMuted,
fontWeight: FontWeight.w400,
),
),

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_color_scheme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../data/models/account_models.dart';
import '../../../components/glass_panel.dart';
@@ -116,11 +116,9 @@ class HoldingRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final accentColor = isDark ? colorScheme.secondary : colorScheme.primary;
final accentColor = context.appColors.accentPrimary;
final accentBgColor = accentColor.withValues(alpha: 0.1);
final profitColor = isProfit ? AppColorScheme.getUpColor(isDark) : AppColorScheme.getDownColor(isDark);
final profitColor = isProfit ? context.appColors.up : context.appColors.down;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: 14),
@@ -159,7 +157,7 @@ class HoldingRow extends StatelessWidget {
quantity,
style: AppTextStyles.bodyMedium(context).copyWith(
fontWeight: FontWeight.w400,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
],

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_color_scheme.dart';
import '../../../../core/theme/app_theme_extension.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../components/glass_panel.dart';
@@ -16,9 +16,7 @@ class RecordsLinkRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final mutedColor = isDark ? AppColorScheme.darkOnSurfaceMuted : colorScheme.onSurfaceVariant;
final mutedColor = context.appColors.onSurfaceMuted;
return GestureDetector(
onTap: onTap,

View File

@@ -3,7 +3,7 @@ import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/theme/app_color_scheme.dart';
import '../../../core/theme/app_theme_extension.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../providers/asset_provider.dart';
import '../../../data/models/account_models.dart';
@@ -76,12 +76,6 @@ class _TransferPageState extends State<TransferPage> {
String get _fromBalance => _direction == 1 ? _fundBalance : _tradeUsdtBalance;
String get _toBalance => _direction == 1 ? _tradeUsdtBalance : _fundBalance;
// ============================================
// 主题辅助
// ============================================
bool get _isDark => Theme.of(context).brightness == Brightness.dark;
// ============================================
// 业务逻辑
// ============================================
@@ -363,7 +357,7 @@ class _TransferPageState extends State<TransferPage> {
decoration: InputDecoration(
hintText: '0.00',
hintStyle: AppTextStyles.numberLarge(context).copyWith(
color: AppColorScheme.darkOnSurfaceMuted,
color: context.appColors.onSurfaceMuted,
),
border: InputBorder.none,
contentPadding: EdgeInsets.zero,
@@ -375,7 +369,7 @@ class _TransferPageState extends State<TransferPage> {
padding: const EdgeInsets.only(left: AppSpacing.sm),
child: Text('USDT', style: AppTextStyles.headlineMedium(context).copyWith(
fontWeight: FontWeight.w400,
color: AppColorScheme.darkOnSurfaceMuted,
color: context.appColors.onSurfaceMuted,
)),
),
],
@@ -425,13 +419,13 @@ class _TransferPageState extends State<TransferPage> {
// ============================================
Widget _buildTipsCard() {
final upColor = AppColorScheme.getUpColor(_isDark);
final upColor = context.appColors.up;
return Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: 12),
decoration: BoxDecoration(
color: AppColorScheme.getUpBackgroundColor(_isDark),
color: context.appColors.upBackground,
borderRadius: BorderRadius.circular(AppRadius.lg),
),
child: Row(

View File

@@ -5,6 +5,7 @@ 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/auth_provider.dart';
import '../main/main_page.dart';
import 'register_page.dart';
@@ -36,12 +37,8 @@ class _LoginPageState extends State<LoginPage> {
@override
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
return Scaffold(
backgroundColor: isDark
? AppColorScheme.darkBackground
: AppColorScheme.lightSurface,
backgroundColor: context.colors.surface,
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(
@@ -53,13 +50,13 @@ class _LoginPageState extends State<LoginPage> {
child: Column(
children: [
// 顶部品牌区域
_buildBrandSection(isDark),
_buildBrandSection(),
const SizedBox(height: AppSpacing.xxl),
// 表单区域
_buildFormSection(isDark),
_buildFormSection(),
const SizedBox(height: AppSpacing.xl),
// 底部注册链接
_buildRegisterRow(isDark),
_buildRegisterRow(),
],
),
),
@@ -72,16 +69,16 @@ class _LoginPageState extends State<LoginPage> {
// 品牌区域 - Logo + 品牌名 + 标语
// ============================================
Widget _buildBrandSection(bool isDark) {
Widget _buildBrandSection() {
return Column(
children: [
// Logo 圆形:渐变 #1F2937 → #374151内含 "M"
Container(
width: _logoCircleSize,
height: _logoCircleSize,
decoration: BoxDecoration(
decoration: const BoxDecoration(
shape: BoxShape.circle,
gradient: const LinearGradient(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [AppColorScheme.darkSurfaceContainerHigh, AppColorScheme.darkOutline],
@@ -93,9 +90,7 @@ class _LoginPageState extends State<LoginPage> {
style: AppTextStyles.displayLarge(context).copyWith(
fontSize: 32,
fontWeight: FontWeight.w800,
color: isDark
? AppColorScheme.darkOnSurface
: AppColorScheme.darkOnPrimary,
color: context.colors.onPrimary,
),
),
),
@@ -105,9 +100,7 @@ class _LoginPageState extends State<LoginPage> {
'MONISUO',
style: AppTextStyles.displayLarge(context).copyWith(
letterSpacing: 3,
color: isDark
? AppColorScheme.darkOnSurface
: AppColorScheme.lightOnSurface,
color: context.colors.onSurface,
),
textAlign: TextAlign.center,
),
@@ -116,9 +109,7 @@ class _LoginPageState extends State<LoginPage> {
Text(
'虚拟货币模拟交易平台',
style: AppTextStyles.bodyLarge(context).copyWith(
color: isDark
? AppColorScheme.darkOnSurfaceVariant
: AppColorScheme.lightOnSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
textAlign: TextAlign.center,
),
@@ -130,30 +121,20 @@ class _LoginPageState extends State<LoginPage> {
// 表单区域 - 用户名 + 密码 + 登录按钮
// ============================================
Widget _buildFormSection(bool isDark) {
Widget _buildFormSection() {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildUsernameField(isDark),
_buildUsernameField(),
const SizedBox(height: AppSpacing.md),
_buildPasswordField(isDark),
_buildPasswordField(),
const SizedBox(height: AppSpacing.sm),
_buildLoginButton(isDark),
_buildLoginButton(),
],
);
}
Widget _buildUsernameField(bool isDark) {
final borderColor = isDark
? AppColorScheme.darkOutlineVariant
: AppColorScheme.lightOutlineVariant;
final cardColor = isDark
? AppColorScheme.darkSurfaceContainer
: AppColorScheme.lightSurfaceLowest;
final iconColor = isDark
? AppColorScheme.darkOnSurfaceMuted
: AppColorScheme.lightOnSurfaceMuted;
Widget _buildUsernameField() {
return SizedBox(
height: _inputHeight,
child: ShadInputFormField(
@@ -161,32 +142,25 @@ class _LoginPageState extends State<LoginPage> {
placeholder: const Text('请输入用户名'),
leading: Padding(
padding: const EdgeInsets.only(right: AppSpacing.sm),
child: Icon(LucideIcons.user, size: 18, color: iconColor),
child: Icon(LucideIcons.user, size: 18, color: context.appColors.onSurfaceMuted),
),
validator: _validateUsername,
controller: _usernameController,
decoration: ShadDecoration(
border: ShadBorder.all(
color: borderColor,
color: context.colors.outlineVariant,
radius: AppRadius.radiusLg,
),
),
style: AppTextStyles.headlineMedium(context).copyWith(
color: isDark
? AppColorScheme.darkOnSurface
: AppColorScheme.lightOnSurface,
color: context.colors.onSurface,
),
),
);
}
Widget _buildPasswordField(bool isDark) {
final borderColor = isDark
? AppColorScheme.darkOutlineVariant
: AppColorScheme.lightOutlineVariant;
final iconColor = isDark
? AppColorScheme.darkOnSurfaceMuted
: AppColorScheme.lightOnSurfaceMuted;
Widget _buildPasswordField() {
final iconColor = context.appColors.onSurfaceMuted;
return SizedBox(
height: _inputHeight,
@@ -210,27 +184,21 @@ class _LoginPageState extends State<LoginPage> {
controller: _passwordController,
decoration: ShadDecoration(
border: ShadBorder.all(
color: borderColor,
color: context.colors.outlineVariant,
radius: AppRadius.radiusLg,
),
),
style: AppTextStyles.headlineMedium(context).copyWith(
color: isDark
? AppColorScheme.darkOnSurface
: AppColorScheme.lightOnSurface,
color: context.colors.onSurface,
),
),
);
}
Widget _buildLoginButton(bool isDark) {
Widget _buildLoginButton() {
// 设计稿: accent-primary = light:#1F2937 / dark:#D4AF37
final buttonColor = isDark
? AppColorScheme.darkSecondary
: AppColorScheme.darkSurfaceContainerHigh;
final textColor = isDark
? AppColorScheme.darkBackground
: AppColorScheme.darkOnPrimary;
final buttonColor = context.appColors.accentPrimary;
final textColor = context.colors.onPrimary;
return Consumer<AuthProvider>(
builder: (context, auth, _) {
@@ -270,14 +238,10 @@ class _LoginPageState extends State<LoginPage> {
// 底部注册链接
// ============================================
Widget _buildRegisterRow(bool isDark) {
Widget _buildRegisterRow() {
// gold-accent: light=#F59E0B / dark=#D4AF37
final goldColor = isDark
? AppColorScheme.darkSecondary
: AppColorScheme.darkSecondaryFixed;
final secondaryTextColor = isDark
? AppColorScheme.darkOnSurfaceVariant
: AppColorScheme.lightOnSurfaceVariant;
final goldColor = context.appColors.accentPrimary;
final secondaryTextColor = context.colors.onSurfaceVariant;
return Padding(
padding: const EdgeInsets.only(bottom: AppSpacing.xl),

View File

@@ -7,13 +7,13 @@ import 'package:provider/provider.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/theme/app_color_scheme.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_theme_extension.dart';
import '../../../core/utils/toast_utils.dart';
import '../../../core/event/app_event_bus.dart';
import '../../../data/models/account_models.dart';
import '../../../data/services/asset_service.dart';
import '../../../data/services/bonus_service.dart';
import '../../../providers/asset_provider.dart';
import '../../../providers/auth_provider.dart';
import '../../components/glass_panel.dart';
import '../../components/neon_glow.dart';
import '../main/main_page.dart';
@@ -85,15 +85,14 @@ class _HomePageState extends State<HomePage>
@override
Widget build(BuildContext context) {
super.build(context);
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
backgroundColor: colorScheme.background,
backgroundColor: context.colors.background,
body: Consumer<AssetProvider>(
builder: (context, provider, _) {
return RefreshIndicator(
onRefresh: () => provider.refreshAll(force: true),
color: colorScheme.primary,
color: context.colors.primary,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.only(
@@ -149,7 +148,6 @@ class _HomePageState extends State<HomePage>
void _showDeposit() {
final amountController = TextEditingController();
final formKey = GlobalKey<ShadFormState>();
final colorScheme = Theme.of(context).colorScheme;
showShadDialog(
context: context,
@@ -184,10 +182,10 @@ class _HomePageState extends State<HomePage>
Container(
padding: EdgeInsets.all(AppSpacing.sm),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHigh,
color: context.colors.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.md),
),
child: Icon(LucideIcons.wallet, color: colorScheme.secondary),
child: Icon(LucideIcons.wallet, color: context.colors.secondary),
),
],
),
@@ -261,7 +259,6 @@ class _HomePageState extends State<HomePage>
final amount = data['amount']?.toString() ?? '0.00';
final walletAddress = data['walletAddress'] as String? ?? '';
final walletNetwork = data['walletNetwork'] as String? ?? 'TRC20';
final colorScheme = Theme.of(context).colorScheme;
showShadDialog(
context: context,
@@ -305,9 +302,9 @@ class _HomePageState extends State<HomePage>
Container(
padding: EdgeInsets.all(AppSpacing.sm),
decoration: BoxDecoration(
color: AppColorScheme.warning.withOpacity(0.1),
color: AppColorScheme.warning.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(AppRadius.md),
border: Border.all(color: AppColorScheme.warning.withOpacity(0.2)),
border: Border.all(color: AppColorScheme.warning.withValues(alpha: 0.2)),
),
child: Row(
children: [
@@ -371,7 +368,6 @@ class _HomePageState extends State<HomePage>
}
void _showResultDialog(String title, String? message) {
final colorScheme = Theme.of(context).colorScheme;
showShadDialog(
context: context,
builder: (ctx) => Dialog(
@@ -525,10 +521,8 @@ class _AssetCardState extends State<_AssetCard> {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final upColor = AppColorScheme.getUpColor(isDark);
final downColor = AppColorScheme.getDownColor(isDark);
final upColor = context.appColors.up;
final downColor = context.appColors.down;
final isProfit = _totalProfit >= 0;
final todayProfit = _todayProfit;
final isTodayProfit = (todayProfit ?? 0) >= 0;
@@ -558,19 +552,19 @@ class _AssetCardState extends State<_AssetCard> {
vertical: AppSpacing.xs + 2,
),
decoration: BoxDecoration(
color: colorScheme.primary.withOpacity(0.1),
color: context.colors.primary.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(AppRadius.full),
border: Border.all(color: colorScheme.primary.withOpacity(0.2)),
border: Border.all(color: context.colors.primary.withValues(alpha: 0.2)),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add, size: 14, color: colorScheme.primary),
Icon(Icons.add, size: 14, color: context.colors.primary),
SizedBox(width: AppSpacing.xs),
Text(
'充值',
style: AppTextStyles.labelLarge(context).copyWith(
color: colorScheme.primary,
color: context.colors.primary,
),
),
],
@@ -620,11 +614,11 @@ class _AssetCardState extends State<_AssetCard> {
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: _calendarExpanded
? colorScheme.primary.withOpacity(0.1)
: colorScheme.surfaceContainerHigh,
? context.colors.primary.withValues(alpha: 0.1)
: context.colors.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.full),
border: _calendarExpanded
? Border.all(color: colorScheme.primary.withOpacity(0.2))
? Border.all(color: context.colors.primary.withValues(alpha: 0.2))
: null,
),
child: Row(
@@ -634,8 +628,8 @@ class _AssetCardState extends State<_AssetCard> {
LucideIcons.chartBar,
size: 13,
color: _calendarExpanded
? colorScheme.primary
: colorScheme.onSurfaceVariant,
? context.colors.primary
: context.colors.onSurfaceVariant,
),
SizedBox(width: AppSpacing.xs),
Text(
@@ -643,8 +637,8 @@ class _AssetCardState extends State<_AssetCard> {
style: AppTextStyles.labelMedium(context).copyWith(
fontWeight: _calendarExpanded ? FontWeight.w600 : FontWeight.w500,
color: _calendarExpanded
? colorScheme.primary
: colorScheme.onSurfaceVariant,
? context.colors.primary
: context.colors.onSurfaceVariant,
),
),
SizedBox(width: 2),
@@ -655,8 +649,8 @@ class _AssetCardState extends State<_AssetCard> {
LucideIcons.chevronDown,
size: 13,
color: _calendarExpanded
? colorScheme.primary
: colorScheme.onSurfaceVariant,
? context.colors.primary
: context.colors.onSurfaceVariant,
),
),
],
@@ -669,9 +663,7 @@ class _AssetCardState extends State<_AssetCard> {
// 可折叠的盈利日历
AnimatedCrossFade(
firstChild: const SizedBox.shrink(),
secondChild: _buildCalendarSection(
context, colorScheme, isDark, upColor, downColor,
),
secondChild: _buildCalendarSection(context),
crossFadeState: _calendarExpanded
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
@@ -683,18 +675,14 @@ class _AssetCardState extends State<_AssetCard> {
);
}
Widget _buildCalendarSection(
BuildContext context,
ColorScheme colorScheme,
bool isDark,
Color upColor,
Color downColor,
) {
Widget _buildCalendarSection(BuildContext context) {
final now = DateTime.now();
final isCurrentMonth = _currentMonth.year == now.year && _currentMonth.month == now.month;
final firstDayOfMonth = DateTime(_currentMonth.year, _currentMonth.month, 1);
final daysInMonth = DateTime(_currentMonth.year, _currentMonth.month + 1, 0).day;
final startWeekday = firstDayOfMonth.weekday;
final upColor = context.appColors.up;
final downColor = context.appColors.down;
return Column(
mainAxisSize: MainAxisSize.min,
@@ -702,7 +690,7 @@ class _AssetCardState extends State<_AssetCard> {
// 分隔线
Padding(
padding: EdgeInsets.symmetric(vertical: AppSpacing.md),
child: Divider(color: colorScheme.outlineVariant.withOpacity(0.15), height: 1),
child: Divider(color: context.appColors.ghostBorder, height: 1),
),
// 月份导航行
@@ -714,10 +702,10 @@ class _AssetCardState extends State<_AssetCard> {
child: Container(
padding: EdgeInsets.all(AppSpacing.xs + 1),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHigh,
color: context.colors.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Icon(LucideIcons.chevronLeft, size: 16, color: colorScheme.onSurfaceVariant),
child: Icon(LucideIcons.chevronLeft, size: 16, color: context.colors.onSurfaceVariant),
),
),
Column(
@@ -745,16 +733,16 @@ class _AssetCardState extends State<_AssetCard> {
padding: EdgeInsets.all(AppSpacing.xs + 1),
decoration: BoxDecoration(
color: isCurrentMonth
? colorScheme.surfaceContainerHigh.withOpacity(0.5)
: colorScheme.surfaceContainerHigh,
? context.colors.surfaceContainerHigh.withValues(alpha: 0.5)
: context.colors.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Icon(
LucideIcons.chevronRight,
size: 16,
color: isCurrentMonth
? colorScheme.onSurfaceVariant.withOpacity(0.4)
: colorScheme.onSurfaceVariant,
? context.colors.onSurfaceVariant.withValues(alpha: 0.4)
: context.colors.onSurfaceVariant,
),
),
),
@@ -771,7 +759,7 @@ class _AssetCardState extends State<_AssetCard> {
d,
style: AppTextStyles.bodySmall(context).copyWith(
fontWeight: FontWeight.w500,
color: colorScheme.onSurfaceVariant.withOpacity(0.6),
color: context.colors.onSurfaceVariant.withValues(alpha: 0.6),
),
),
),
@@ -789,14 +777,13 @@ class _AssetCardState extends State<_AssetCard> {
height: 18,
child: CircularProgressIndicator(
strokeWidth: 2,
color: colorScheme.primary,
color: context.colors.primary,
),
),
)
else
..._buildCalendarGrid(
startWeekday, daysInMonth, now, isCurrentMonth,
upColor, downColor, colorScheme,
),
],
);
@@ -807,10 +794,9 @@ class _AssetCardState extends State<_AssetCard> {
int daysInMonth,
DateTime now,
bool isCurrentMonth,
Color upColor,
Color downColor,
ColorScheme colorScheme,
) {
final upColor = context.appColors.up;
final downColor = context.appColors.down;
final List<Widget> rows = [];
List<Widget> cells = [];
@@ -831,15 +817,15 @@ class _AssetCardState extends State<_AssetCard> {
margin: EdgeInsets.all(1),
decoration: BoxDecoration(
color: isToday
? colorScheme.primary.withOpacity(0.12)
? context.colors.primary.withValues(alpha: 0.12)
: hasProfit
? (profit! > 0
? upColor.withOpacity(0.08)
: downColor.withOpacity(0.08))
? upColor.withValues(alpha: 0.08)
: downColor.withValues(alpha: 0.08))
: Colors.transparent,
borderRadius: BorderRadius.circular(AppRadius.sm),
border: isToday
? Border.all(color: colorScheme.primary.withOpacity(0.4), width: 1)
? Border.all(color: context.colors.primary.withValues(alpha: 0.4), width: 1)
: null,
),
child: Column(
@@ -851,8 +837,8 @@ class _AssetCardState extends State<_AssetCard> {
fontSize: 10,
fontWeight: isToday ? FontWeight.bold : FontWeight.w400,
color: isToday
? colorScheme.primary
: colorScheme.onSurface,
? context.colors.primary
: context.colors.onSurface,
),
),
if (hasProfit) ...[
@@ -906,9 +892,6 @@ class _WelfareCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return GestureDetector(
onTap: onTap,
child: Container(
@@ -917,14 +900,14 @@ class _WelfareCard extends StatelessWidget {
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
colorScheme.primary.withOpacity(0.15),
colorScheme.secondary.withOpacity(0.1),
context.colors.primary.withValues(alpha: 0.15),
context.colors.secondary.withValues(alpha: 0.1),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(AppRadius.xl),
border: Border.all(color: colorScheme.primary.withOpacity(0.2)),
border: Border.all(color: context.colors.primary.withValues(alpha: 0.2)),
),
child: Row(
children: [
@@ -933,12 +916,12 @@ class _WelfareCard extends StatelessWidget {
width: 48,
height: 48,
decoration: BoxDecoration(
color: colorScheme.primary.withOpacity(0.15),
color: context.colors.primary.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(AppRadius.lg),
),
child: Icon(
LucideIcons.gift,
color: colorScheme.primary,
color: context.colors.primary,
size: 24,
),
),
@@ -971,9 +954,7 @@ class _WelfareCard extends StatelessWidget {
vertical: AppSpacing.sm,
),
decoration: BoxDecoration(
gradient: isDark
? AppColorScheme.darkCtaGradient
: AppColorScheme.lightCtaGradient,
gradient: context.appColors.ctaGradient,
borderRadius: BorderRadius.circular(AppRadius.full),
),
child: Row(
@@ -1000,7 +981,7 @@ class _WelfareCard extends StatelessWidget {
'查看',
style: AppTextStyles.headlineSmall(context).copyWith(
fontWeight: FontWeight.w700,
color: isDark ? colorScheme.background : AppColorScheme.darkOnPrimary,
color: context.colors.onPrimary,
),
),
],
@@ -1021,8 +1002,6 @@ class _HoldingsSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Column(
children: [
Row(
@@ -1037,7 +1016,7 @@ class _HoldingsSection extends StatelessWidget {
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: colorScheme.primary,
foregroundColor: context.colors.primary,
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.sm),
),
child: Row(
@@ -1048,7 +1027,7 @@ class _HoldingsSection extends StatelessWidget {
)),
const SizedBox(width: AppSpacing.xs),
Icon(LucideIcons.chevronRight,
size: 16, color: colorScheme.primary),
size: 16, color: context.colors.primary),
],
),
),
@@ -1067,19 +1046,17 @@ class _EmptyHoldings extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: AppSpacing.xxl, horizontal: AppSpacing.lg),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerLow.withOpacity(0.5),
color: context.colors.surfaceContainerLow.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(AppRadius.xxl),
border: Border.all(color: colorScheme.outlineVariant.withOpacity(0.1)),
border: Border.all(color: context.colors.outlineVariant.withValues(alpha: 0.1)),
),
child: Column(
children: [
Icon(LucideIcons.wallet, size: 48, color: colorScheme.onSurfaceVariant),
Icon(LucideIcons.wallet, size: 48, color: context.colors.onSurfaceVariant),
SizedBox(height: AppSpacing.md),
Text(
'暂无持仓',
@@ -1106,15 +1083,14 @@ class _HoldingsList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final displayHoldings =
holdings.length > 5 ? holdings.sublist(0, 5) : holdings;
return Container(
decoration: BoxDecoration(
color: colorScheme.surface.withOpacity(0.5),
color: context.colors.surface.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(AppRadius.xxl),
border: Border.all(color: colorScheme.outlineVariant.withOpacity(0.1)),
border: Border.all(color: context.colors.outlineVariant.withValues(alpha: 0.1)),
),
child: ListView.separated(
shrinkWrap: true,
@@ -1122,7 +1098,7 @@ class _HoldingsList extends StatelessWidget {
padding: EdgeInsets.all(AppSpacing.md),
itemCount: displayHoldings.length,
separatorBuilder: (_, __) => Divider(
color: colorScheme.outlineVariant.withOpacity(0.1),
color: context.colors.outlineVariant.withValues(alpha: 0.1),
height: 1,
),
itemBuilder: (context, index) =>
@@ -1140,9 +1116,6 @@ class _HoldingItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Padding(
padding: EdgeInsets.symmetric(vertical: AppSpacing.sm + AppSpacing.xs),
child: Row(
@@ -1152,11 +1125,11 @@ class _HoldingItem extends StatelessWidget {
children: [
CircleAvatar(
radius: 18,
backgroundColor: colorScheme.primary.withOpacity(0.1),
backgroundColor: context.colors.primary.withValues(alpha: 0.1),
child: Text(
holding.coinCode.substring(0, 1),
style: AppTextStyles.headlineMedium(context).copyWith(
color: colorScheme.primary,
color: context.colors.primary,
fontWeight: FontWeight.bold,
),
),
@@ -1185,8 +1158,8 @@ class _HoldingItem extends StatelessWidget {
Text(holding.formattedProfitRate,
style: AppTextStyles.numberSmall(context).copyWith(
color: holding.isProfit
? AppColorScheme.getUpColor(isDark)
: AppColorScheme.getDownColor(isDark),
? context.appColors.up
: context.appColors.down,
)),
],
),
@@ -1206,8 +1179,6 @@ class _InfoRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -1232,14 +1203,12 @@ class _WalletAddressCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
padding: EdgeInsets.all(AppSpacing.md),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHigh,
color: context.colors.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.md),
border: Border.all(color: colorScheme.outlineVariant.withOpacity(0.3)),
border: Border.all(color: context.colors.outlineVariant.withValues(alpha: 0.3)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -1262,11 +1231,11 @@ class _WalletAddressCard extends StatelessWidget {
child: Container(
padding: EdgeInsets.all(AppSpacing.xs),
decoration: BoxDecoration(
color: colorScheme.primary.withOpacity(0.1),
color: context.colors.primary.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Icon(LucideIcons.copy,
size: 16, color: colorScheme.primary),
size: 16, color: context.colors.primary),
),
),
],
@@ -1298,22 +1267,21 @@ class _ProfitStatCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final hasValue = value != null;
final isProfit = (value ?? 0) >= 0;
final color = hasValue ? (isProfit ? upColor : downColor) : colorScheme.onSurfaceVariant;
final color = hasValue ? (isProfit ? upColor : downColor) : context.colors.onSurfaceVariant;
return Container(
padding: EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm + 2),
decoration: BoxDecoration(
color: hasValue
? (isProfit ? upColor : downColor).withOpacity(0.06)
: colorScheme.surfaceContainerHigh.withOpacity(0.5),
? (isProfit ? upColor : downColor).withValues(alpha: 0.06)
: context.colors.surfaceContainerHigh.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: hasValue
? (isProfit ? upColor : downColor).withOpacity(0.12)
: colorScheme.outlineVariant.withOpacity(0.1),
? (isProfit ? upColor : downColor).withValues(alpha: 0.12)
: context.colors.outlineVariant.withValues(alpha: 0.1),
),
),
child: Column(
@@ -1326,14 +1294,14 @@ class _ProfitStatCard extends StatelessWidget {
? (isProfit ? LucideIcons.trendingUp : LucideIcons.trendingDown)
: LucideIcons.minus,
size: 11,
color: color.withOpacity(0.7),
color: color.withValues(alpha: 0.7),
),
SizedBox(width: 3),
Text(
label,
style: AppTextStyles.bodySmall(context).copyWith(
fontWeight: FontWeight.w500,
color: color.withOpacity(0.8),
color: color.withValues(alpha: 0.8),
),
),
],

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/theme/app_color_scheme.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_theme_extension.dart';
/// 首页热门币种区块
class HotCoinsSection extends StatelessWidget {
@@ -10,9 +10,6 @@ class HotCoinsSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Column(
children: [
// Title row
@@ -36,9 +33,9 @@ class HotCoinsSection extends StatelessWidget {
// Card
Container(
decoration: BoxDecoration(
color: colorScheme.surfaceContainer,
color: context.colors.surfaceContainer,
border: Border.all(
color: colorScheme.outlineVariant,
color: context.colors.outlineVariant,
width: 1,
),
borderRadius: BorderRadius.circular(AppRadius.xl),
@@ -52,13 +49,11 @@ class HotCoinsSection extends StatelessWidget {
price: '68,432.50',
change: '+2.35%',
isUp: true,
colorScheme: colorScheme,
isDark: isDark,
),
Divider(
height: 1,
thickness: 1,
color: colorScheme.outlineVariant.withValues(alpha: 0.15),
color: context.appColors.ghostBorder,
),
_CoinRow(
symbol: 'ETH',
@@ -67,13 +62,11 @@ class HotCoinsSection extends StatelessWidget {
price: '3,856.20',
change: '+1.82%',
isUp: true,
colorScheme: colorScheme,
isDark: isDark,
),
Divider(
height: 1,
thickness: 1,
color: colorScheme.outlineVariant.withValues(alpha: 0.15),
color: context.appColors.ghostBorder,
),
_CoinRow(
symbol: 'SOL',
@@ -82,8 +75,6 @@ class HotCoinsSection extends StatelessWidget {
price: '178.65',
change: '-0.94%',
isUp: false,
colorScheme: colorScheme,
isDark: isDark,
),
],
),
@@ -101,8 +92,6 @@ class _CoinRow extends StatelessWidget {
required this.price,
required this.change,
required this.isUp,
required this.colorScheme,
required this.isDark,
});
final String symbol;
@@ -111,14 +100,12 @@ class _CoinRow extends StatelessWidget {
final String price;
final String change;
final bool isUp;
final ColorScheme colorScheme;
final bool isDark;
@override
Widget build(BuildContext context) {
final changeColor = isUp
? AppColorScheme.getUpColor(isDark)
: AppColorScheme.getDownColor(isDark);
? context.appColors.up
: context.appColors.down;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 14, horizontal: AppSpacing.md),
@@ -130,13 +117,13 @@ class _CoinRow extends StatelessWidget {
children: [
CircleAvatar(
radius: 18,
backgroundColor: colorScheme.primary.withValues(alpha: 0.1),
backgroundColor: context.colors.primary.withValues(alpha: 0.1),
child: Text(
symbol,
style: AppTextStyles.bodySmall(context).copyWith(
fontSize: 10,
fontWeight: FontWeight.w700,
color: colorScheme.primary,
color: context.colors.primary,
),
),
),

View File

@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/theme/app_color_scheme.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_theme_extension.dart';
import '../../../data/services/asset_service.dart';
/// 盈亏分析页面 - 月度盈亏日历
@@ -26,26 +26,6 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
WidgetsBinding.instance.addPostFrameCallback((_) => _loadProfit());
}
// ============================================
// 主题感知颜色
// ============================================
bool get _isDark => Theme.of(context).brightness == Brightness.dark;
Color get _upColor => AppColorScheme.getUpColor(_isDark);
Color get _downColor => AppColorScheme.getDownColor(_isDark);
Color get _scaffoldBg =>
_isDark ? AppColorScheme.darkBackground : AppColorScheme.lightBackground;
Color get _cardBg => _isDark
? AppColorScheme.darkSurfaceContainer
: AppColorScheme.lightSurfaceLowest;
Color get _cardBorder => _isDark
? AppColorScheme.darkOutlineVariant.withValues(alpha: 0.15)
: AppColorScheme.lightOutlineVariant.withValues(alpha: 0.5);
// ============================================
// 数据加载
// ============================================
@@ -111,16 +91,15 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final now = DateTime.now();
final isCurrentMonth =
_currentMonth.year == now.year && _currentMonth.month == now.month;
return Scaffold(
backgroundColor: _scaffoldBg,
backgroundColor: context.colors.surface,
appBar: AppBar(
title: const Text('盈亏分析'),
backgroundColor: _scaffoldBg,
backgroundColor: context.colors.surface,
elevation: 0,
scrolledUnderElevation: 0,
centerTitle: true,
@@ -130,31 +109,30 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
child: Container(
padding: EdgeInsets.all(AppSpacing.lg),
decoration: BoxDecoration(
color: _cardBg,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.xl),
border: Border.all(color: _cardBorder),
border: Border.all(color: context.appColors.ghostBorder),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 月度盈亏摘要
_buildSummarySection(colorScheme),
_buildSummarySection(),
SizedBox(height: AppSpacing.md),
// 月份导航
_buildMonthNavigation(colorScheme, isCurrentMonth),
_buildMonthNavigation(isCurrentMonth),
SizedBox(height: AppSpacing.sm),
// 星期标题
_buildWeekdayHeaders(colorScheme),
_buildWeekdayHeaders(),
SizedBox(height: AppSpacing.xs),
// 日历网格
if (_isLoading)
_buildLoadingIndicator(colorScheme)
_buildLoadingIndicator()
else
..._buildCalendarGrid(
colorScheme,
now,
isCurrentMonth,
),
@@ -166,16 +144,18 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
}
/// 月度盈亏摘要
Widget _buildSummarySection(ColorScheme colorScheme) {
Widget _buildSummarySection() {
final upColor = context.appColors.up;
final downColor = context.appColors.down;
final isProfit = _monthProfit >= 0;
final color = _isLoading ? colorScheme.onSurfaceVariant : (isProfit ? _upColor : _downColor);
final color = _isLoading ? context.colors.onSurfaceVariant : (isProfit ? upColor : downColor);
return Column(
children: [
Text(
'月度盈亏',
style: AppTextStyles.bodyMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
SizedBox(height: AppSpacing.xs),
@@ -193,7 +173,7 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
}
/// 月份导航行
Widget _buildMonthNavigation(ColorScheme colorScheme, bool isCurrentMonth) {
Widget _buildMonthNavigation(bool isCurrentMonth) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -203,13 +183,13 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
child: Container(
padding: EdgeInsets.all(AppSpacing.xs + 1),
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHigh,
color: context.colors.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Icon(
LucideIcons.chevronLeft,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
),
@@ -227,16 +207,16 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
padding: EdgeInsets.all(AppSpacing.xs + 1),
decoration: BoxDecoration(
color: isCurrentMonth
? colorScheme.surfaceContainerHigh.withValues(alpha: 0.5)
: colorScheme.surfaceContainerHigh,
? context.colors.surfaceContainerHigh.withValues(alpha: 0.5)
: context.colors.surfaceContainerHigh,
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Icon(
LucideIcons.chevronRight,
size: 16,
color: isCurrentMonth
? colorScheme.onSurfaceVariant.withValues(alpha: 0.4)
: colorScheme.onSurfaceVariant,
? context.colors.onSurfaceVariant.withValues(alpha: 0.4)
: context.colors.onSurfaceVariant,
),
),
),
@@ -245,7 +225,7 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
}
/// 星期标题行
Widget _buildWeekdayHeaders(ColorScheme colorScheme) {
Widget _buildWeekdayHeaders() {
return Row(
children: ['', '', '', '', '', '', ''].map((d) {
return Expanded(
@@ -254,7 +234,7 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
d,
style: AppTextStyles.bodySmall(context).copyWith(
fontWeight: FontWeight.w500,
color: colorScheme.onSurfaceVariant.withValues(alpha: 0.6),
color: context.colors.onSurfaceVariant.withValues(alpha: 0.6),
),
),
),
@@ -264,7 +244,7 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
}
/// 加载指示器
Widget _buildLoadingIndicator(ColorScheme colorScheme) {
Widget _buildLoadingIndicator() {
return Padding(
padding: EdgeInsets.symmetric(vertical: AppSpacing.xxl),
child: Center(
@@ -273,7 +253,7 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
color: colorScheme.primary,
color: context.colors.primary,
),
),
),
@@ -282,10 +262,11 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
/// 日历网格
List<Widget> _buildCalendarGrid(
ColorScheme colorScheme,
DateTime now,
bool isCurrentMonth,
) {
final upColor = context.appColors.up;
final downColor = context.appColors.down;
final firstDayOfMonth = DateTime(_currentMonth.year, _currentMonth.month, 1);
final daysInMonth =
DateTime(_currentMonth.year, _currentMonth.month + 1, 0).day;
@@ -313,16 +294,16 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
margin: EdgeInsets.all(1),
decoration: BoxDecoration(
color: isToday
? colorScheme.primary.withValues(alpha: 0.12)
? context.colors.primary.withValues(alpha: 0.12)
: hasProfit
? (profit! > 0
? _upColor.withValues(alpha: 0.08)
: _downColor.withValues(alpha: 0.08))
? upColor.withValues(alpha: 0.08)
: downColor.withValues(alpha: 0.08))
: Colors.transparent,
borderRadius: BorderRadius.circular(AppRadius.sm),
border: isToday
? Border.all(
color: colorScheme.primary.withValues(alpha: 0.4),
color: context.colors.primary.withValues(alpha: 0.4),
width: 1,
)
: null,
@@ -336,8 +317,8 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
fontSize: 10,
fontWeight: isToday ? FontWeight.bold : FontWeight.w400,
color: isToday
? colorScheme.primary
: colorScheme.onSurface,
? context.colors.primary
: context.colors.onSurface,
),
),
if (hasProfit) ...[
@@ -347,7 +328,7 @@ class _ProfitAnalysisPageState extends State<ProfitAnalysisPage> {
style: TextStyle(
fontSize: 7,
fontWeight: FontWeight.w600,
color: profit > 0 ? _upColor : _downColor,
color: profit > 0 ? upColor : downColor,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,

View File

@@ -2,9 +2,9 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.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 '../../../data/models/coin.dart';
import '../../../providers/market_provider.dart';
import '../../components/glass_panel.dart';
@@ -34,10 +34,9 @@ class _MarketPageState extends State<MarketPage>
@override
Widget build(BuildContext context) {
super.build(context);
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
backgroundColor: colorScheme.background,
backgroundColor: context.colors.surface,
body: Consumer<MarketProvider>(
builder: (context, provider, _) {
if (provider.isLoading) {
@@ -50,8 +49,8 @@ class _MarketPageState extends State<MarketPage>
return RefreshIndicator(
onRefresh: () => provider.refresh(),
color: colorScheme.primary,
backgroundColor: colorScheme.surfaceContainerHighest,
color: context.colors.primary,
backgroundColor: context.colors.surfaceContainerHighest,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.only(
@@ -114,8 +113,6 @@ class _MarketPageState extends State<MarketPage>
/// 分区标题:全部币种 + 更多
Widget _buildSectionHeader() {
final colorScheme = Theme.of(context).colorScheme;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -126,7 +123,7 @@ class _MarketPageState extends State<MarketPage>
Text(
'更多 >',
style: AppTextStyles.bodyMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
],
@@ -136,7 +133,6 @@ class _MarketPageState extends State<MarketPage>
/// 币种列表
Widget _buildCoinList(MarketProvider provider) {
final coins = provider.otherCoins;
final colorScheme = Theme.of(context).colorScheme;
if (coins.isEmpty) {
return _EmptyState(
@@ -148,10 +144,10 @@ class _MarketPageState extends State<MarketPage>
return Container(
decoration: BoxDecoration(
color: colorScheme.surfaceContainer,
color: context.colors.surfaceContainer,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withValues(alpha: 0.15),
color: context.appColors.ghostBorder,
width: 1,
),
),
@@ -162,7 +158,7 @@ class _MarketPageState extends State<MarketPage>
separatorBuilder: (_, __) => Divider(
height: 1,
thickness: 1,
color: colorScheme.outlineVariant.withValues(alpha: 0.5 * 0.15),
color: context.colors.outlineVariant.withValues(alpha: 0.5 * 0.15),
indent: AppSpacing.md,
endIndent: AppSpacing.md,
),
@@ -173,18 +169,17 @@ class _MarketPageState extends State<MarketPage>
/// 错误状态
Widget _buildErrorState(MarketProvider provider) {
final colorScheme = Theme.of(context).colorScheme;
return Center(
child: Padding(
padding: AppSpacing.pagePadding,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(LucideIcons.circleAlert, size: 48, color: colorScheme.error),
Icon(LucideIcons.circleAlert, size: 48, color: context.colors.error),
const SizedBox(height: AppSpacing.md),
Text(
provider.error ?? '加载失败',
style: TextStyle(color: colorScheme.error),
style: TextStyle(color: context.colors.error),
textAlign: TextAlign.center,
),
const SizedBox(height: AppSpacing.md),
@@ -207,14 +202,12 @@ class _FeaturedCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final isUp = coin.isUp;
final changeColor =
isUp ? AppColorScheme.getUpColor(isDark) : AppColorScheme.down;
isUp ? context.appColors.up : context.appColors.down;
final changeBgColor = isUp
? AppColorScheme.getUpBackgroundColor(isDark)
: AppColorScheme.getDownBackgroundColor(isDark);
? context.appColors.upBackground
: context.appColors.downBackground;
return GlassPanel(
padding: const EdgeInsets.all(AppSpacing.md),
@@ -255,12 +248,12 @@ class _FeaturedCard extends StatelessWidget {
Text(
coin.name,
style: AppTextStyles.bodyMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
// 第四行:迷你柱状图
Expanded(
child: _MiniBarChart(isUp: isUp, isDark: isDark, seed: coin.code.hashCode),
child: _MiniBarChart(isUp: isUp, seed: coin.code.hashCode),
),
],
),
@@ -295,16 +288,15 @@ class _FeaturedCard extends StatelessWidget {
/// 迷你柱状图(模拟价格走势)
class _MiniBarChart extends StatelessWidget {
final bool isUp;
final bool isDark;
final int seed;
const _MiniBarChart({required this.isUp, required this.isDark, required this.seed});
const _MiniBarChart({required this.isUp, required this.seed});
@override
Widget build(BuildContext context) {
final barColor = isUp
? AppColorScheme.getUpColor(isDark)
: AppColorScheme.getDownColor(isDark);
? context.appColors.up
: context.appColors.down;
// 生成随机但确定的高度序列
final heights = _generateHeights();
@@ -345,14 +337,12 @@ class _CoinRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final isUp = coin.isUp;
final changeColor =
isUp ? AppColorScheme.getUpColor(isDark) : AppColorScheme.getDownColor(isDark);
isUp ? context.appColors.up : context.appColors.down;
final changeBgColor = isUp
? AppColorScheme.getUpBackgroundColor(isDark)
: AppColorScheme.getDownBackgroundColor(isDark);
? context.appColors.upBackground
: context.appColors.downBackground;
return GestureDetector(
onTap: () => _navigateToTrade(context),
@@ -428,12 +418,8 @@ class _CoinAvatar extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
// 从 .pen 设计中的 accent-light 和 accent-primary
final bgColor = colorScheme.primary.withValues(alpha: isDark ? 0.15 : 0.1);
final textColor = colorScheme.primary;
final bgColor = context.colors.primary.withValues(alpha: context.appColors.glowOpacity);
return Container(
width: 36,
@@ -447,7 +433,7 @@ class _CoinAvatar extends StatelessWidget {
_getLetter(),
style: AppTextStyles.labelLarge(context).copyWith(
fontWeight: FontWeight.w700,
color: textColor,
color: context.colors.primary,
),
),
),
@@ -477,18 +463,16 @@ class _EmptyState extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Center(
child: Padding(
padding: const EdgeInsets.all(AppSpacing.xl),
child: Column(
children: [
Icon(icon, size: 48, color: colorScheme.onSurfaceVariant),
Icon(icon, size: 48, color: context.colors.onSurfaceVariant),
const SizedBox(height: AppSpacing.sm + AppSpacing.xs),
Text(
message,
style: TextStyle(color: colorScheme.onSurfaceVariant),
style: TextStyle(color: context.colors.onSurfaceVariant),
),
if (onRetry != null) ...[
const SizedBox(height: AppSpacing.md),

View File

@@ -3,6 +3,7 @@ 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';
@@ -22,9 +23,6 @@ class MenuGroup1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return MenuGroupContainer(
child: Column(
children: [
@@ -44,7 +42,7 @@ class MenuGroup1 extends StatelessWidget {
// 实名认证
MenuRow(
icon: LucideIcons.shieldCheck,
iconColor: AppColorScheme.getUpColor(isDark),
iconColor: context.appColors.up,
title: '实名认证',
trailing: KycBadge(kycStatus: kycStatus),
onTap: () {
@@ -62,7 +60,7 @@ class MenuGroup1 extends StatelessWidget {
// 安全设置
MenuRow(
icon: LucideIcons.lock,
iconColor: colorScheme.onSurfaceVariant,
iconColor: context.colors.onSurfaceVariant,
title: '安全设置',
onTap: () => onShowComingSoon('安全设置'),
),
@@ -70,7 +68,7 @@ class MenuGroup1 extends StatelessWidget {
// 消息通知
MenuRow(
icon: LucideIcons.bell,
iconColor: colorScheme.onSurfaceVariant,
iconColor: context.colors.onSurfaceVariant,
title: '消息通知',
trailing: const RedDotIndicator(),
onTap: () => onShowComingSoon('消息通知'),

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme_extension.dart';
/// 菜单分组容器 - 统一的圆角卡片样式
///
@@ -12,19 +13,14 @@ class MenuGroupContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
width: double.infinity,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainer
: colorScheme.surfaceContainerHigh,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.15),
color: context.appColors.ghostBorder,
),
),
child: child,

View File

@@ -4,6 +4,7 @@ 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)
@@ -18,9 +19,7 @@ class KycBadge extends StatelessWidget {
@override
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final green = AppColorScheme.getUpColor(isDark);
final colorScheme = Theme.of(context).colorScheme;
final green = context.appColors.up;
if (kycStatus == 2) {
return Row(
@@ -43,7 +42,7 @@ class KycBadge extends StatelessWidget {
Icon(
LucideIcons.chevronRight,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
],
);
@@ -70,7 +69,7 @@ class KycBadge extends StatelessWidget {
Icon(
LucideIcons.chevronRight,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
],
);
@@ -79,7 +78,7 @@ class KycBadge extends StatelessWidget {
return Icon(
LucideIcons.chevronRight,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
);
}
}
@@ -105,7 +104,7 @@ class RedDotIndicator extends StatelessWidget {
Icon(
LucideIcons.chevronRight,
size: 16,
color: Theme.of(context).colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
],
);
@@ -118,8 +117,6 @@ class DarkModeRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final themeProvider = context.watch<ThemeProvider>();
return Padding(
@@ -131,16 +128,14 @@ class DarkModeRow extends StatelessWidget {
width: 36,
height: 36,
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainerHigh
: colorScheme.surfaceContainerHighest,
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Icon(
LucideIcons.moon,
size: 18,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
),
@@ -160,9 +155,7 @@ class DarkModeRow extends StatelessWidget {
height: 24,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainerHigh
: colorScheme.surfaceContainerHighest,
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(12),
),
child: AnimatedAlign(
@@ -174,7 +167,7 @@ class DarkModeRow extends StatelessWidget {
width: 20,
height: 20,
decoration: BoxDecoration(
color: colorScheme.onSurface,
color: context.colors.onSurface,
shape: BoxShape.circle,
),
),

View File

@@ -2,6 +2,7 @@ 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
@@ -11,19 +12,14 @@ class ProfileCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainer
: colorScheme.surfaceContainerHigh,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withValues(alpha: 0.15),
color: context.appColors.ghostBorder,
),
),
child: Row(
@@ -58,7 +54,7 @@ class ProfileCard extends StatelessWidget {
Icon(
LucideIcons.chevronRight,
size: 16,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
],
),

View File

@@ -2,9 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shadcn_ui/shadcn_ui.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 '../../../core/utils/toast_utils.dart';
import '../../../core/event/app_event_bus.dart';
import '../../../data/services/bonus_service.dart';
@@ -43,70 +43,36 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
}
// ============================================
// 主题感知颜色辅助
// ============================================
bool get _isDark => Theme.of(context).brightness == Brightness.dark;
/// 金色强调色 ($gold-accent)
Color get _goldAccent =>
_isDark ? AppColorScheme.darkSecondary : const Color(0xFFF59E0B);
/// 盈利绿色 ($profit-green)
Color get _profitGreen =>
_isDark ? const Color(0xFF4ADE80) : const Color(0xFF16A34A);
/// 盈利绿色背景 ($profit-green-bg)
Color get _profitGreenBg =>
_isDark ? const Color(0xFF052E16) : const Color(0xFFF0FDF4);
/// 文字静默色 ($text-muted)
Color get _textMuted =>
_isDark ? AppColorScheme.darkOnSurfaceMuted : AppColorScheme.lightOnSurfaceMuted;
/// 第三级背景色 ($bg-tertiary)
Color get _bgTertiary =>
_isDark ? AppColorScheme.darkSurfaceContainerHigh : AppColorScheme.lightSurfaceContainer;
/// 卡片表面色 ($surface-card)
Color get _surfaceCard =>
_isDark ? AppColorScheme.darkSurfaceContainer : AppColorScheme.lightSurfaceLowest;
/// 反色文字 ($text-inverse)
Color get _textInverse =>
_isDark ? AppColorScheme.darkInverseSurface : AppColorScheme.lightSurfaceLowest;
// ============================================
// 容器样式辅助
// ============================================
/// 标准卡片容器
BoxDecoration _cardDecoration({Color? borderColor}) {
final scheme = Theme.of(context).colorScheme;
return BoxDecoration(
color: _surfaceCard,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: borderColor ?? scheme.outlineVariant.withValues(alpha: 0.15),
color: borderColor ?? context.appColors.ghostBorder,
),
);
}
/// 金色渐变卡片容器
BoxDecoration _goldGradientDecoration() {
final goldAccent = context.appColors.accentPrimary;
return BoxDecoration(
borderRadius: BorderRadius.circular(AppRadius.xl),
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
_goldAccent.withValues(alpha: 0.15),
_surfaceCard,
goldAccent.withValues(alpha: 0.15),
context.appColors.surfaceCard,
],
),
border: Border.all(
color: _goldAccent.withValues(alpha: 0.3),
color: goldAccent.withValues(alpha: 0.3),
width: 1,
),
);
@@ -164,16 +130,12 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final goldAccent = context.appColors.accentPrimary;
return Scaffold(
backgroundColor: _isDark
? AppColorScheme.darkBackground
: AppColorScheme.lightBackground,
backgroundColor: context.colors.surface,
appBar: AppBar(
backgroundColor: _isDark
? AppColorScheme.darkBackground
: AppColorScheme.lightSurfaceLowest,
backgroundColor: context.colors.surface,
elevation: 0,
scrolledUnderElevation: 0,
centerTitle: false,
@@ -183,20 +145,20 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
style: AppTextStyles.headlineLarge(context),
),
leading: IconButton(
icon: Icon(LucideIcons.arrowLeft, color: colorScheme.onSurface, size: 24),
icon: Icon(LucideIcons.arrowLeft, color: context.colors.onSurface, size: 24),
onPressed: () => Navigator.of(context).pop(),
),
),
body: _isLoading
? Center(
child: CircularProgressIndicator(
color: _goldAccent,
color: goldAccent,
strokeWidth: 2.5,
),
)
: RefreshIndicator(
onRefresh: _loadData,
color: _goldAccent,
color: goldAccent,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.fromLTRB(16, 8, 16, 32),
@@ -222,7 +184,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// ============================================
Widget _buildReferralCodeCard(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final goldAccent = context.appColors.accentPrimary;
final referralCode = _welfareData?['referralCode'] as String? ?? '';
return Container(
@@ -235,7 +197,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// Header Row: gift icon + 标题
Row(
children: [
Icon(LucideIcons.gift, color: _goldAccent, size: 24),
Icon(LucideIcons.gift, color: goldAccent, size: 24),
const SizedBox(width: 10),
Text(
'我的邀请码',
@@ -250,7 +212,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
referralCode.isEmpty ? '暂无邀请码' : referralCode,
style: AppTextStyles.displayMedium(context).copyWith(
fontWeight: FontWeight.w800,
color: _goldAccent,
color: goldAccent,
letterSpacing: 2,
),
),
@@ -266,17 +228,17 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
ToastUtils.show('邀请码已复制');
},
style: ElevatedButton.styleFrom(
backgroundColor: _goldAccent,
foregroundColor: _textInverse,
backgroundColor: goldAccent,
foregroundColor: context.colors.onSurface,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppRadius.lg),
),
disabledBackgroundColor: _goldAccent.withValues(alpha: 0.4),
disabledBackgroundColor: goldAccent.withValues(alpha: 0.4),
),
child: Text(
'复制邀请码',
style: AppTextStyles.headlineMedium(context).copyWith(color: _textInverse),
style: AppTextStyles.headlineMedium(context).copyWith(color: context.colors.onSurface),
),
),
),
@@ -290,7 +252,8 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// ============================================
Widget _buildNewUserBonusCard(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final profitGreen = context.appColors.up;
final profitGreenBg = context.appColors.upBackground;
final newUserBonus = _welfareData?['newUserBonus'] as Map<String, dynamic>?;
final eligible = newUserBonus?['eligible'] as bool? ?? false;
final claimed = newUserBonus?['claimed'] as bool? ?? false;
@@ -341,7 +304,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
),
),
if (showAvailableBadge)
_statusBadge(badgeText, _profitGreen, _profitGreenBg),
_statusBadge(badgeText, profitGreen, profitGreenBg),
],
),
const SizedBox(height: 12),
@@ -349,21 +312,21 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
'+100 USDT',
style: AppTextStyles.displayLarge(context).copyWith(
fontWeight: FontWeight.w800,
color: claimed ? colorScheme.onSurfaceVariant : _profitGreen,
color: claimed ? context.colors.onSurfaceVariant : profitGreen,
),
),
const SizedBox(height: 8),
Text(
description,
style: AppTextStyles.bodyLarge(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
const SizedBox(height: 16),
_fullWidthButton(
text: buttonText,
backgroundColor: _profitGreen,
foregroundColor: colorScheme.onPrimary,
backgroundColor: profitGreen,
foregroundColor: context.colors.onPrimary,
onPressed: canClaim ? () => _claimNewUserBonus() : null,
),
],
@@ -376,7 +339,6 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// ============================================
Widget _buildReferralRewardsSection(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final referralRewards =
_welfareData?['referralRewards'] as List<dynamic>? ?? [];
@@ -392,7 +354,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
Text(
'每邀请一位好友充值达标奖励100 USDT',
style: AppTextStyles.bodySmall(context).copyWith(
color: _textMuted,
color: context.appColors.onSurfaceMuted,
),
),
const SizedBox(height: 12),
@@ -410,7 +372,6 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
Widget _buildEmptyReferralList(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Padding(
padding: const EdgeInsets.all(32),
child: Center(
@@ -419,13 +380,13 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
Icon(
LucideIcons.users,
size: 36,
color: _textMuted.withValues(alpha: 0.4),
color: context.appColors.onSurfaceMuted.withValues(alpha: 0.4),
),
const SizedBox(height: 8),
Text(
'暂无推广用户',
style: AppTextStyles.bodyLarge(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
],
@@ -435,8 +396,6 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
Widget _buildReferralListItems(BuildContext context, List<dynamic> referralRewards) {
final colorScheme = Theme.of(context).colorScheme;
return Column(
children: List.generate(referralRewards.length, (index) {
final data = referralRewards[index] as Map<String, dynamic>;
@@ -492,7 +451,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
height: 6,
child: LinearProgressIndicator(
value: progress,
backgroundColor: _bgTertiary,
backgroundColor: context.appColors.surfaceCardHigh,
valueColor: AlwaysStoppedAnimation<Color>(progressColor),
minHeight: 6,
),
@@ -505,7 +464,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
Divider(
height: 1,
thickness: 1,
color: colorScheme.outlineVariant.withValues(alpha: 0.15),
color: context.appColors.ghostBorder,
),
],
);
@@ -514,19 +473,18 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
Widget _buildAvatar(String username) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: _bgTertiary,
color: context.appColors.surfaceCardHigh,
shape: BoxShape.circle,
),
child: Center(
child: Text(
username.isNotEmpty ? username[0].toUpperCase() : '?',
style: AppTextStyles.headlineSmall(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
),
@@ -548,9 +506,9 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
/// 根据状态获取进度条颜色
Color _referralProgressColor(int claimableCount, double progress) {
if (claimableCount > 0) return _profitGreen;
if (progress > 0) return _goldAccent;
return _bgTertiary;
if (claimableCount > 0) return context.appColors.up;
if (progress > 0) return context.appColors.accentPrimary;
return context.appColors.surfaceCardHigh;
}
/// 构建推荐奖励的操作按钮
@@ -560,6 +518,9 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
required List<dynamic> milestones,
required double progress,
}) {
final profitGreen = context.appColors.up;
final profitGreenBg = context.appColors.upBackground;
if (claimableCount > 0) {
final int milestoneValue = milestones.isNotEmpty
? (milestones.firstWhere(
@@ -570,7 +531,7 @@ 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) {
@@ -578,7 +539,7 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
return Text(
'待达标',
style: AppTextStyles.labelLarge(context).copyWith(color: _textMuted),
style: AppTextStyles.labelLarge(context).copyWith(color: context.appColors.onSurfaceMuted),
);
}
@@ -587,13 +548,11 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
// ============================================
Widget _buildRulesCard(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Container(
width: double.infinity,
padding: const EdgeInsets.fromLTRB(20, 16, 20, 16),
decoration: BoxDecoration(
color: _bgTertiary,
color: context.appColors.surfaceCardHigh,
borderRadius: BorderRadius.circular(AppRadius.lg),
),
child: Column(
@@ -613,15 +572,12 @@ class _WelfareCenterPageState extends State<WelfareCenterPage> {
}
Widget _buildRuleItem(String text) {
final ruleTextColor = _isDark
? AppColorScheme.darkOnSurfaceVariant
: const Color(0xFF475569);
return Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Text(
'\u2022 $text',
style: AppTextStyles.bodyMedium(context).copyWith(
color: ruleTextColor,
color: context.colors.onSurfaceVariant,
),
),
);

View File

@@ -3,6 +3,7 @@ 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.dart';
import '../../../core/theme/app_theme_extension.dart';
import '../../../core/storage/local_storage.dart';
/// 引导页数据模型
@@ -91,11 +92,8 @@ class _OnboardingPageState extends State<OnboardingPage> {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Scaffold(
backgroundColor: colorScheme.surface,
backgroundColor: context.colors.surface,
body: SafeArea(
child: Column(
children: [
@@ -113,7 +111,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
child: Text(
'跳过',
style: AppTextStyles.headlineMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
),
@@ -131,7 +129,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
},
itemCount: _items.length,
itemBuilder: (context, index) {
return _buildPage(_items[index], isDark);
return _buildPage(_items[index]);
},
),
),
@@ -150,7 +148,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
_items.length,
(index) => _buildIndicator(index, isDark),
(index) => _buildIndicator(index),
),
),
const SizedBox(height: AppSpacing.xl),
@@ -161,8 +159,8 @@ class _OnboardingPageState extends State<OnboardingPage> {
child: ElevatedButton(
onPressed: _nextPage,
style: ElevatedButton.styleFrom(
backgroundColor: colorScheme.primary,
foregroundColor: colorScheme.onPrimary,
backgroundColor: context.colors.primary,
foregroundColor: context.colors.onPrimary,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppRadius.lg),
),
@@ -185,9 +183,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
);
}
Widget _buildPage(_OnboardingItem item, bool isDark) {
final colorScheme = Theme.of(context).colorScheme;
Widget _buildPage(_OnboardingItem item) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.xl),
child: Column(
@@ -225,7 +221,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
return Icon(
item.icon ?? LucideIcons.image,
size: 72,
color: AppColorScheme.darkOnPrimary,
color: context.colors.onPrimary,
);
},
),
@@ -233,7 +229,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
: Icon(
item.icon ?? LucideIcons.star,
size: 72,
color: AppColorScheme.darkOnPrimary,
color: context.colors.onPrimary,
),
),
),
@@ -243,7 +239,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
item.title,
style: AppTextStyles.displaySmall(context).copyWith(
fontWeight: FontWeight.bold,
color: colorScheme.onSurface,
color: context.colors.onSurface,
letterSpacing: -0.5,
),
),
@@ -253,7 +249,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
item.description,
textAlign: TextAlign.center,
style: AppTextStyles.headlineMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
height: 1.6,
),
),
@@ -262,8 +258,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
);
}
Widget _buildIndicator(int index, bool isDark) {
final colorScheme = Theme.of(context).colorScheme;
Widget _buildIndicator(int index) {
final isActive = index == _currentPage;
return AnimatedContainer(
@@ -272,7 +267,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
width: isActive ? 24 : 8,
height: 8,
decoration: BoxDecoration(
color: isActive ? colorScheme.primary : colorScheme.outlineVariant,
color: isActive ? context.colors.primary : context.colors.outlineVariant,
borderRadius: BorderRadius.circular(AppRadius.sm),
),
);

View File

@@ -4,6 +4,7 @@ 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/asset_provider.dart';
import '../../../data/models/order_models.dart';
import 'fund_order_card.dart';
@@ -88,8 +89,6 @@ class _FundOrderCardContent extends StatelessWidget {
const _FundOrderCardContent({required this.order});
bool get _isDark => true; // 默认深色
Color _getStatusColor(int status, bool isDeposit) {
if (isDeposit) {
switch (status) {
@@ -159,8 +158,6 @@ class _FundOrderCardContent extends StatelessWidget {
final theme = ShadTheme.of(context);
final isDeposit = order.type == 1;
final statusColor = _getStatusColor(order.status, isDeposit);
final isDark = Theme.of(context).brightness == Brightness.dark;
final onPrimaryColor = isDark ? AppColorScheme.darkOnSurface : AppColorScheme.lightOnSurface;
return ShadCard(
padding: AppSpacing.cardPadding,

View File

@@ -7,6 +7,7 @@ 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 '../../../core/utils/toast_utils.dart';
import '../../../core/event/app_event_bus.dart';
import '../../../providers/asset_provider.dart';
@@ -51,32 +52,21 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
context.read<AssetProvider>().loadFundOrders(type: type);
}
// ============================================
// 主题辅助
// ============================================
bool get _isDark => Theme.of(context).brightness == Brightness.dark;
/// 一次性获取所有主题感知颜色
_OrderColors get _colors => _OrderColors(_isDark);
// ============================================
// 构建 UI
// ============================================
@override
Widget build(BuildContext context) {
final c = _colors;
return Scaffold(
backgroundColor: c.background,
backgroundColor: context.colors.surface,
appBar: AppBar(
leading: IconButton(
icon: const Icon(LucideIcons.arrowLeft, size: 20),
onPressed: () => Navigator.of(context).pop(),
),
title: Text('充提记录', style: AppTextStyles.headlineLarge(context).copyWith(color: c.primaryText)),
backgroundColor: c.background,
title: Text('充提记录', style: AppTextStyles.headlineLarge(context).copyWith(color: context.colors.onSurface)),
backgroundColor: context.colors.surface,
elevation: 0,
scrolledUnderElevation: 0,
centerTitle: true,
@@ -94,15 +84,13 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
// Filter Tabs - pill-style segmented control
// ---------------------------------------------------------------------------
Widget _buildFilterTabs() {
final c = _colors;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md),
child: Container(
height: 40,
padding: const EdgeInsets.all(AppSpacing.xs),
decoration: BoxDecoration(
color: c.tabBg,
color: context.appColors.surfaceCardHigh,
borderRadius: AppRadius.radiusMd,
),
child: Row(
@@ -117,7 +105,6 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
}
Widget _buildPillTab(String label, int index) {
final c = _colors;
final isActive = _activeTab == index;
return Expanded(
@@ -130,15 +117,15 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
},
child: Container(
decoration: BoxDecoration(
color: isActive ? c.activeTabBg : AppColorScheme.darkSurfaceLowest.withValues(alpha: 0),
color: isActive ? context.colors.onSurface : AppColorScheme.darkSurfaceLowest.withValues(alpha: 0),
borderRadius: AppRadius.radiusSm,
),
child: Center(
child: Text(
label,
style: isActive
? AppTextStyles.headlineMedium(context).copyWith(color: c.activeTabText)
: AppTextStyles.headlineSmall(context).copyWith(color: c.inactiveTabText),
? AppTextStyles.headlineMedium(context).copyWith(color: context.colors.surface)
: AppTextStyles.headlineSmall(context).copyWith(color: context.colors.onSurfaceVariant),
),
),
),
@@ -150,8 +137,6 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
// Order List
// ---------------------------------------------------------------------------
Widget _buildOrderList() {
final c = _colors;
return Consumer<AssetProvider>(
builder: (context, provider, _) {
final orders = provider.fundOrders;
@@ -166,9 +151,9 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(LucideIcons.inbox, size: 64, color: c.mutedText),
Icon(LucideIcons.inbox, size: 64, color: context.appColors.onSurfaceMuted),
const SizedBox(height: AppSpacing.md),
Text('暂无订单记录', style: AppTextStyles.headlineMedium(context).copyWith(color: c.secondaryText)),
Text('暂无订单记录', style: AppTextStyles.headlineMedium(context).copyWith(color: context.colors.onSurfaceVariant)),
],
),
);
@@ -193,14 +178,12 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
// Order Card
// ---------------------------------------------------------------------------
Widget _buildOrderCard(OrderFund order) {
final c = _colors;
return Container(
padding: AppSpacing.cardPadding,
decoration: BoxDecoration(
color: c.cardBg,
color: context.appColors.surfaceCard,
borderRadius: AppRadius.radiusLg,
border: Border.all(color: c.borderColor, width: 1),
border: Border.all(color: context.appColors.ghostBorder, width: 1),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -216,7 +199,7 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
],
if (order.withdrawContact != null) ...[
const SizedBox(height: AppSpacing.sm - AppSpacing.xs),
_buildDetailRow('联系方式', order.withdrawContact!, c),
_buildDetailRow('联系方式', order.withdrawContact!),
],
if (order.receivableAmount != null && !order.isDeposit) ...[
const SizedBox(height: AppSpacing.sm),
@@ -232,13 +215,13 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
children: [
Text(
'创建: ${_formatTime(order.createTime)}',
style: AppTextStyles.bodySmall(context).copyWith(color: c.mutedText),
style: AppTextStyles.bodySmall(context).copyWith(color: context.appColors.onSurfaceMuted),
),
if (order.rejectReason != null)
Expanded(
child: Text(
'驳回: ${order.rejectReason}',
style: AppTextStyles.bodySmall(context).copyWith(color: AppColorScheme.getDownColor(_isDark)),
style: AppTextStyles.bodySmall(context).copyWith(color: context.appColors.down),
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
),
@@ -254,13 +237,12 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
// Card Header (order type + status badge)
// ---------------------------------------------------------------------------
Widget _buildCardHeader(OrderFund order) {
final c = _colors;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
order.isDeposit ? '充值' : '提现',
style: AppTextStyles.headlineMedium(context).copyWith(color: c.primaryText),
style: AppTextStyles.headlineMedium(context).copyWith(color: context.colors.onSurface),
),
_buildStatusBadge(order),
],
@@ -268,10 +250,10 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
}
Widget _buildStatusBadge(OrderFund order) {
final upColor = AppColorScheme.getUpColor(_isDark);
final downColor = AppColorScheme.getDownColor(_isDark);
final upBg = AppColorScheme.getUpBackgroundColor(_isDark, opacity: 0.12);
final downBg = AppColorScheme.getDownBackgroundColor(_isDark, opacity: 0.12);
final upColor = context.appColors.up;
final downColor = context.appColors.down;
final upBg = context.appColors.up.withValues(alpha: 0.12);
final downBg = context.appColors.down.withValues(alpha: 0.12);
Color bgColor;
Color textColor;
@@ -326,10 +308,9 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
// Amount Row
// ---------------------------------------------------------------------------
Widget _buildAmountRow(OrderFund order) {
final c = _colors;
return Text(
'${order.isDeposit ? '+' : '-'}${order.amount} USDT',
style: AppTextStyles.displaySmall(context).copyWith(color: c.primaryText, height: 1.3),
style: AppTextStyles.displaySmall(context).copyWith(color: context.colors.onSurface, height: 1.3),
);
}
@@ -337,44 +318,39 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
// Detail Rows
// ---------------------------------------------------------------------------
Widget _buildDetailRows(OrderFund order) {
final c = _colors;
return Column(
children: [
_buildDetailRow('订单号', order.orderNo, c),
_buildDetailRow('订单号', order.orderNo),
const SizedBox(height: AppSpacing.sm - AppSpacing.xs),
if (order.walletAddress != null) ...[
_buildDetailRow(
'网络',
order.remark.isNotEmpty ? order.remark : '-',
c,
),
const SizedBox(height: AppSpacing.sm - AppSpacing.xs),
_buildDetailRow(
'地址',
_truncateAddress(order.walletAddress!),
c,
trailing: GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(text: order.walletAddress!));
ToastUtils.show('地址已复制');
},
child: Icon(LucideIcons.copy, size: 14, color: c.mutedText),
child: Icon(LucideIcons.copy, size: 14, color: context.appColors.onSurfaceMuted),
),
),
const SizedBox(height: AppSpacing.sm - AppSpacing.xs),
] else if (order.remark.isNotEmpty) ...[
_buildDetailRow('网络', order.remark, c),
_buildDetailRow('网络', order.remark),
const SizedBox(height: AppSpacing.sm - AppSpacing.xs),
],
if (order.fee != null && !order.isDeposit) ...[
_buildDetailRow('手续费', '${order.fee}%', c),
_buildDetailRow('手续费', '${order.fee}%'),
const SizedBox(height: AppSpacing.sm - AppSpacing.xs),
],
_buildDetailRow(
'时间',
_formatTime(order.createTime),
c,
),
],
);
@@ -382,16 +358,15 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
Widget _buildDetailRow(
String label,
String value,
_OrderColors c, {
String value, {
Widget? trailing,
}) {
final valueStyle = AppTextStyles.bodyMedium(context).copyWith(color: c.primaryText);
final valueStyle = AppTextStyles.bodyMedium(context).copyWith(color: context.colors.onSurface);
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(label, style: AppTextStyles.bodyMedium(context).copyWith(color: c.mutedText)),
Text(label, style: AppTextStyles.bodyMedium(context).copyWith(color: context.appColors.onSurfaceMuted)),
if (trailing != null)
Row(
mainAxisSize: MainAxisSize.min,
@@ -413,7 +388,7 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
Widget _buildRejectionReason(OrderFund order) {
return Text(
'拒绝原因: ${order.rejectReason}',
style: AppTextStyles.bodyMedium(context).copyWith(color: AppColorScheme.getDownColor(_isDark)),
style: AppTextStyles.bodyMedium(context).copyWith(color: context.appColors.down),
);
}
@@ -421,19 +396,17 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
// Payable Amount Row (withdrawal)
// ---------------------------------------------------------------------------
Widget _buildPayableRow(OrderFund order) {
final c = _colors;
return Container(
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.sm + AppSpacing.xs, vertical: AppSpacing.sm),
decoration: BoxDecoration(
color: c.bgTertiary,
color: context.appColors.surfaceCardHigh,
borderRadius: AppRadius.radiusSm,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('应付金额', style: AppTextStyles.headlineSmall(context).copyWith(color: c.secondaryText)),
Text('${order.receivableAmount} USDT', style: AppTextStyles.headlineMedium(context).copyWith(color: c.primaryText)),
Text('应付金额', style: AppTextStyles.headlineSmall(context).copyWith(color: context.colors.onSurfaceVariant)),
Text('${order.receivableAmount} USDT', style: AppTextStyles.headlineMedium(context).copyWith(color: context.colors.onSurface)),
],
),
);
@@ -443,9 +416,8 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
// Action Buttons
// ---------------------------------------------------------------------------
Widget _buildActions(OrderFund order) {
final upColor = AppColorScheme.getUpColor(_isDark);
final downColor = AppColorScheme.getDownColor(_isDark);
final c = _colors;
final upColor = context.appColors.up;
final downColor = context.appColors.down;
return Row(
mainAxisAlignment: MainAxisAlignment.end,
@@ -473,7 +445,7 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
color: upColor,
borderRadius: AppRadius.radiusSm,
),
child: Text('已打款', style: AppTextStyles.headlineSmall(context).copyWith(color: c.activeTabText)),
child: Text('已打款', style: AppTextStyles.headlineSmall(context).copyWith(color: context.colors.surface)),
),
),
],
@@ -552,37 +524,3 @@ class _FundOrdersPageState extends State<FundOrdersPage> {
);
}
}
/// 充提订单页面的主题感知颜色集合
class _OrderColors {
final Color background;
final Color cardBg;
final Color borderColor;
final Color bgTertiary;
final Color primaryText;
final Color secondaryText;
final Color mutedText;
final Color tabBg;
final Color activeTabBg;
final Color activeTabText;
final Color inactiveTabText;
_OrderColors(bool isDark)
: background = isDark ? AppColorScheme.darkBackground : AppColorScheme.lightBackground,
cardBg = isDark ? AppColorScheme.darkSurfaceContainer : AppColorScheme.lightSurfaceLowest,
borderColor = isDark
? AppColorScheme.darkOutlineVariant.withValues(alpha: 0.15)
: AppColorScheme.lightOutlineVariant.withValues(alpha: 0.5),
bgTertiary = isDark
? AppColorScheme.darkSurfaceContainerHigh
: AppColorScheme.lightSurfaceHigh,
primaryText = isDark ? AppColorScheme.darkOnSurface : AppColorScheme.lightOnSurface,
secondaryText = isDark
? AppColorScheme.darkOnSurfaceVariant
: AppColorScheme.lightOnSurfaceVariant,
mutedText = isDark ? AppColorScheme.darkOnSurfaceMuted : AppColorScheme.lightOnSurfaceMuted,
tabBg = isDark ? AppColorScheme.darkSurfaceContainerHigh : AppColorScheme.lightSurfaceHigh,
activeTabBg = isDark ? AppColorScheme.darkOnSurface : AppColorScheme.lightSurfaceLowest,
activeTabText = isDark ? AppColorScheme.darkBackground : AppColorScheme.lightOnSurface,
inactiveTabText = isDark ? AppColorScheme.darkOnSurfaceVariant : AppColorScheme.lightOnSurfaceVariant;
}

View File

@@ -4,6 +4,7 @@ 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/asset_provider.dart';
import 'fund_orders_list.dart';
@@ -35,7 +36,6 @@ class _OrdersPageState extends State<OrdersPage> with AutomaticKeepAliveClientMi
Widget build(BuildContext context) {
super.build(context);
final theme = ShadTheme.of(context);
final isDark = Theme.of(context).brightness == Brightness.dark;
return Scaffold(
backgroundColor: theme.colorScheme.background,
@@ -84,8 +84,6 @@ class TabSelector extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = ShadTheme.of(context);
final isDark = Theme.of(context).brightness == Brightness.dark;
final onPrimaryBg = isDark ? AppColorScheme.darkBackground : AppColorScheme.lightSurfaceLowest;
return Container(
padding: const EdgeInsets.all(AppSpacing.xs),
@@ -114,7 +112,7 @@ class TabSelector extends StatelessWidget {
label,
style: isSelected
? AppTextStyles.labelLarge(context).copyWith(
color: onPrimaryBg,
color: context.colors.surface,
)
: AppTextStyles.labelLarge(context).copyWith(
color: theme.colorScheme.mutedForeground,

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:lucide_icons_flutter/lucide_icons.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 '../../../../data/models/coin.dart';
import 'coin_avatar.dart';
@@ -25,21 +25,16 @@ class CoinSelector extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return GestureDetector(
onTap: () => _showCoinPicker(context),
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(AppSpacing.md),
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainer
: colorScheme.surfaceContainerLowest,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.15),
color: context.appColors.ghostBorder,
),
),
child: Row(
@@ -60,14 +55,14 @@ class CoinSelector extends StatelessWidget {
Text(
selectedCoin?.name ?? '点击选择交易对',
style: AppTextStyles.bodyMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
],
),
// 下拉箭头
Icon(LucideIcons.chevronDown,
size: 16, color: colorScheme.onSurfaceVariant),
size: 16, color: context.colors.onSurfaceVariant),
],
),
),
@@ -75,9 +70,6 @@ class CoinSelector extends StatelessWidget {
}
void _showCoinPicker(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
showModalBottomSheet(
context: context,
backgroundColor: const Color(0x00000000),
@@ -85,9 +77,9 @@ class CoinSelector extends StatelessWidget {
builder: (ctx) => Container(
height: MediaQuery.of(ctx).size.height * 0.65,
decoration: BoxDecoration(
color: isDark
? colorScheme.surface
: colorScheme.surfaceContainerLowest,
color: ctx.isDark
? ctx.colors.surface
: ctx.colors.surfaceContainerLowest,
borderRadius:
BorderRadius.vertical(top: Radius.circular(AppRadius.xxl)),
),
@@ -99,7 +91,7 @@ class CoinSelector extends StatelessWidget {
width: 40,
height: 4,
decoration: BoxDecoration(
color: colorScheme.onSurfaceVariant.withOpacity(0.3),
color: ctx.colors.onSurfaceVariant.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(AppRadius.sm),
),
),
@@ -114,12 +106,12 @@ class CoinSelector extends StatelessWidget {
GestureDetector(
onTap: () => Navigator.of(ctx).pop(),
child: Icon(LucideIcons.x,
color: colorScheme.onSurfaceVariant),
color: ctx.colors.onSurfaceVariant),
),
],
),
),
Divider(height: 1, color: colorScheme.outlineVariant.withOpacity(0.2)),
Divider(height: 1, color: ctx.colors.outlineVariant.withValues(alpha: 0.2)),
// 币种列表
Expanded(
child: ListView.builder(
@@ -137,12 +129,10 @@ class CoinSelector extends StatelessWidget {
Widget _buildCoinItem(
Coin coin, BuildContext context, BuildContext sheetContext) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final isSelected = selectedCoin?.code == coin.code;
final changeColor = coin.isUp
? AppColorScheme.getUpColor(isDark)
: AppColorScheme.getDownColor(isDark);
? context.appColors.up
: context.appColors.down;
return GestureDetector(
onTap: () {
@@ -153,7 +143,7 @@ class CoinSelector extends StatelessWidget {
padding: EdgeInsets.symmetric(
horizontal: AppSpacing.lg, vertical: AppSpacing.md),
color:
isSelected ? colorScheme.primary.withOpacity(0.1) : const Color(0x00000000),
isSelected ? context.colors.primary.withValues(alpha: 0.1) : const Color(0x00000000),
child: Row(
children: [
CoinAvatar(icon: coin.displayIcon),
@@ -170,7 +160,7 @@ class CoinSelector extends StatelessWidget {
SizedBox(width: AppSpacing.xs),
Text('/USDT',
style: AppTextStyles.bodySmall(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
)),
const Spacer(),
Text('\$${coin.formattedPrice}',
@@ -180,7 +170,7 @@ class CoinSelector extends StatelessWidget {
Container(
padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: changeColor.withOpacity(0.1),
color: changeColor.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Text(coin.formattedChange,
@@ -192,7 +182,7 @@ class CoinSelector extends StatelessWidget {
if (isSelected) ...[
SizedBox(width: AppSpacing.sm),
Icon(LucideIcons.check,
size: 16, color: colorScheme.primary),
size: 16, color: context.colors.primary),
],
],
),
@@ -200,7 +190,7 @@ class CoinSelector extends StatelessWidget {
// 第二行:币种名称
Text(coin.name,
style: AppTextStyles.bodyMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
)),
],
),

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.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 '../../../components/glass_panel.dart';
import '../../../components/neon_glow.dart';
@@ -27,11 +27,9 @@ class ConfirmDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final actionColor = isBuy
? AppColorScheme.getUpColor(isDark)
: AppColorScheme.getDownColor(isDark);
? context.appColors.up
: context.appColors.down;
return Dialog(
backgroundColor: const Color(0x00000000),
@@ -49,14 +47,14 @@ class ConfirmDialog extends StatelessWidget {
),
),
SizedBox(height: AppSpacing.lg),
_dialogRow(context, '交易对', '$coinCode/USDT', colorScheme),
_dialogRow(context, '交易对', '$coinCode/USDT'),
SizedBox(height: AppSpacing.sm),
_dialogRow(context, '委托价格', '$price USDT', colorScheme),
_dialogRow(context, '委托价格', '$price USDT'),
SizedBox(height: AppSpacing.sm),
_dialogRow(context, '交易金额', '$amount USDT', colorScheme,
_dialogRow(context, '交易金额', '$amount USDT',
valueColor: actionColor),
SizedBox(height: AppSpacing.sm),
_dialogRow(context, '交易数量', '$quantity $coinCode', colorScheme),
_dialogRow(context, '交易数量', '$quantity $coinCode'),
SizedBox(height: AppSpacing.lg),
Row(
children: [
@@ -87,7 +85,7 @@ class ConfirmDialog extends StatelessWidget {
);
}
Widget _dialogRow(BuildContext context, String label, String value, ColorScheme colorScheme,
Widget _dialogRow(BuildContext context, String label, String value,
{Color? valueColor}) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -95,11 +93,11 @@ class ConfirmDialog extends StatelessWidget {
Text(label,
style: AppTextStyles.headlineMedium(context).copyWith(
fontWeight: FontWeight.w400,
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
)),
Text(value,
style: AppTextStyles.numberMedium(context).copyWith(
color: valueColor ?? colorScheme.onSurface,
color: valueColor ?? context.colors.onSurface,
)),
],
);

View File

@@ -1,38 +1,34 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_spacing.dart';
import '../../../../core/theme/app_theme.dart';
import '../../../../core/theme/app_theme_extension.dart';
/// 占位卡片组件
///
/// 当未选择币种时显示的占位提示卡片。
class PlaceholderCard extends StatelessWidget {
final String message;
final ColorScheme colorScheme;
const PlaceholderCard({
super.key,
required this.message,
required this.colorScheme,
});
@override
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(AppSpacing.xl),
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainer
: colorScheme.surfaceContainerLowest,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.15),
color: context.appColors.ghostBorder,
),
),
child: Center(
child: Text(message,
style: AppTextStyles.headlineMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
)),
),
);

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.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 '../../../../data/models/coin.dart';
/// 价格卡片组件
@@ -14,25 +14,21 @@ class PriceCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final isUp = coin.isUp;
final changeColor =
isUp ? AppColorScheme.getUpColor(isDark) : AppColorScheme.getDownColor(isDark);
isUp ? context.appColors.up : context.appColors.down;
final changeBgColor = isUp
? AppColorScheme.getUpBackgroundColor(isDark)
: AppColorScheme.getDownBackgroundColor(isDark);
? context.appColors.upBackground
: context.appColors.downBackground;
return Container(
width: double.infinity,
padding: const EdgeInsets.all(AppSpacing.md + AppSpacing.sm),
decoration: BoxDecoration(
color: isDark
? colorScheme.surfaceContainer
: colorScheme.surfaceContainerLowest,
color: context.appColors.surfaceCard,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.15),
color: context.appColors.ghostBorder,
),
),
child: Column(

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.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 '../../../../data/models/coin.dart';
import 'amount_input.dart';
@@ -37,17 +38,13 @@ class TradeFormCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
final isBuy = tradeType == 0;
final actionColor = isBuy
? AppColorScheme.getUpColor(isDark)
: AppColorScheme.getDownColor(isDark);
? context.appColors.up
: context.appColors.down;
// 设计稿中 card 背景色
final cardBgColor = isDark
? colorScheme.surfaceContainer
: colorScheme.surfaceContainerLowest;
final cardBgColor = context.appColors.surfaceCard;
return Container(
width: double.infinity,
@@ -56,7 +53,7 @@ class TradeFormCard extends StatelessWidget {
color: cardBgColor,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.15),
color: context.appColors.ghostBorder,
),
),
child: Column(
@@ -83,7 +80,7 @@ class TradeFormCard extends StatelessWidget {
border: isBuy
? null
: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.15)),
color: context.appColors.ghostBorder),
),
child: Center(
child: Text(
@@ -91,7 +88,7 @@ class TradeFormCard extends StatelessWidget {
style: AppTextStyles.headlineMedium(context).copyWith(
color: isBuy
? AppColorScheme.darkOnPrimary
: colorScheme.onSurfaceVariant,
: context.colors.onSurfaceVariant,
),
),
),
@@ -113,7 +110,7 @@ class TradeFormCard extends StatelessWidget {
border: !isBuy
? null
: Border.all(
color: colorScheme.outlineVariant.withOpacity(0.15)),
color: context.appColors.ghostBorder),
),
child: Center(
child: Text(
@@ -121,7 +118,7 @@ class TradeFormCard extends StatelessWidget {
style: AppTextStyles.headlineMedium(context).copyWith(
color: !isBuy
? AppColorScheme.darkOnPrimary
: colorScheme.onSurfaceVariant,
: context.colors.onSurfaceVariant,
),
),
),
@@ -139,7 +136,7 @@ class TradeFormCard extends StatelessWidget {
children: [
Text('交易金额',
style: AppTextStyles.bodyMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
)),
Text('USDT',
style: AppTextStyles.labelLarge(context)),
@@ -163,7 +160,7 @@ class TradeFormCard extends StatelessWidget {
? '可用: $availableUsdt USDT'
: '可用: $availableCoinQty ${selectedCoin?.code ?? ""}',
style: AppTextStyles.bodySmall(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
),
),
const SizedBox(height: AppSpacing.md),
@@ -172,13 +169,13 @@ class TradeFormCard extends StatelessWidget {
// 设计稿gap:8圆角smbg-tertiary高32
Row(
children: [
_buildPctButton(context, '25%', 0.25, colorScheme),
_buildPctButton(context, '25%', 0.25),
const SizedBox(width: AppSpacing.sm),
_buildPctButton(context, '50%', 0.5, colorScheme),
_buildPctButton(context, '50%', 0.5),
const SizedBox(width: AppSpacing.sm),
_buildPctButton(context, '75%', 0.75, colorScheme),
_buildPctButton(context, '75%', 0.75),
const SizedBox(width: AppSpacing.sm),
_buildPctButton(context, '100%', 1.0, colorScheme),
_buildPctButton(context, '100%', 1.0),
],
),
const SizedBox(height: AppSpacing.md + AppSpacing.sm),
@@ -189,7 +186,7 @@ class TradeFormCard extends StatelessWidget {
children: [
Text('交易数量',
style: AppTextStyles.bodyMedium(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
)),
Text(
'$calculatedQuantity ${selectedCoin?.code ?? ''}',
@@ -203,20 +200,20 @@ class TradeFormCard extends StatelessWidget {
}
/// 百分比按钮 - 设计稿圆角smbg-tertiary高32
Widget _buildPctButton(BuildContext context, String label, double pct, ColorScheme colorScheme) {
Widget _buildPctButton(BuildContext context, String label, double pct) {
return Expanded(
child: GestureDetector(
onTap: () => onFillPercent(pct),
child: Container(
height: 32,
decoration: BoxDecoration(
color: colorScheme.surfaceContainerHighest.withOpacity(0.5),
color: context.colors.surfaceContainerHighest.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(AppRadius.sm),
),
child: Center(
child: Text(label,
style: AppTextStyles.labelLarge(context).copyWith(
color: colorScheme.onSurfaceVariant,
color: context.colors.onSurfaceVariant,
)),
),
),

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'package:provider/provider.dart';
import '../../../core/theme/app_color_scheme.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_theme_extension.dart';
import '../../../data/models/coin.dart';
import '../../../providers/market_provider.dart';
import '../../../providers/asset_provider.dart';
@@ -113,10 +113,9 @@ class _TradePageState extends State<TradePage>
@override
Widget build(BuildContext context) {
super.build(context);
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
backgroundColor: colorScheme.background,
backgroundColor: context.colors.background,
body: Consumer2<MarketProvider, AssetProvider>(
builder: (context, market, asset, _) {
return SafeArea(
@@ -150,7 +149,6 @@ class _TradePageState extends State<TradePage>
else
PlaceholderCard(
message: '请先选择交易币种',
colorScheme: colorScheme,
),
const SizedBox(height: AppSpacing.md),
@@ -262,8 +260,6 @@ class _TradePageState extends State<TradePage>
}
void _showResultDialog(bool success, String title, String message) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
showShadDialog(
context: context,
builder: (ctx) => ShadDialog.alert(
@@ -272,8 +268,8 @@ class _TradePageState extends State<TradePage>
NeonIcon(
icon: success ? Icons.check_circle : Icons.error,
color: success
? AppColorScheme.getUpColor(isDark)
: colorScheme.error,
? ctx.appColors.up
: ctx.colors.error,
size: 24,
),
SizedBox(width: AppSpacing.sm),