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

@@ -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,