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

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