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

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