import 'dart:io'; import 'package:flutter/material.dart'; /// 应用级语义色扩展(浅色/深色各一套,随主题自动切换) /// /// 用法:`context.appColors.cardBackground` /// 原理:颜色挂载在 ThemeData.extensions 上,主题切换时组件树自动重建, /// 页面无需写 `isDark ? A : B` 判断 @immutable class AppColors extends ThemeExtension { const AppColors({ required this.pageBackground, required this.cardBackground, required this.fillBackground, required this.textPrimary, required this.textSecondary, required this.textTertiary, required this.divider, required this.cardShadow, required this.primary, required this.danger, required this.warning, required this.success, }); /// 页面背景色 final Color pageBackground; /// 卡片背景色 final Color cardBackground; /// 卡片内嵌块填充色(输入框、上传按钮等) final Color fillBackground; /// 主要文字色 final Color textPrimary; /// 次要文字色 final Color textSecondary; /// 辅助文字色(占位、说明) final Color textTertiary; /// 分割线/浅色边框 final Color divider; /// 卡片阴影色 final Color cardShadow; /// 品牌主色(两种模式下保持一致) final Color primary; /// 危险/错误色(两种模式下保持一致) final Color danger; /// 警告色(两种模式下保持一致) final Color warning; /// 成功/完成色(两种模式下保持一致) final Color success; /// 浅色语义色(取自设计稿) static const AppColors light = AppColors( pageBackground: Color(0xFFF5F7FA), cardBackground: Color(0xFFFFFFFF), fillBackground: Color(0xFFF8F9FA), textPrimary: Color(0xFF1D2129), textSecondary: Color(0xFF4E5969), textTertiary: Color(0xFF86909C), divider: Color(0xFFF0F0F0), cardShadow: Color(0x0D000000), primary: Color(0xFF165DFF), danger: Color(0xFFF53F3F), warning: Color(0xFFFF7D00), success: Color(0xFF00B42A), ); /// 深色语义色(与 AppTheme.darkTheme 的 surface 色保持一致) static const AppColors dark = AppColors( pageBackground: Color(0xFF1C1C1E), cardBackground: Color(0xFF2C2C2E), fillBackground: Color(0xFF3A3A3C), textPrimary: Color(0xFFF2F3F5), textSecondary: Color(0xFFC9CDD4), textTertiary: Color(0xFF86909C), divider: Color(0xFF3A3A3C), cardShadow: Color(0x00000000), // 深色下无阴影,靠色差分层级 primary: Color(0xFF165DFF), danger: Color(0xFFF53F3F), warning: Color(0xFFFF7D00), success: Color(0xFF00B42A), ); @override AppColors copyWith({ Color? pageBackground, Color? cardBackground, Color? fillBackground, Color? textPrimary, Color? textSecondary, Color? textTertiary, Color? divider, Color? cardShadow, Color? primary, Color? danger, Color? warning, Color? success, }) { return AppColors( pageBackground: pageBackground ?? this.pageBackground, cardBackground: cardBackground ?? this.cardBackground, fillBackground: fillBackground ?? this.fillBackground, textPrimary: textPrimary ?? this.textPrimary, textSecondary: textSecondary ?? this.textSecondary, textTertiary: textTertiary ?? this.textTertiary, divider: divider ?? this.divider, cardShadow: cardShadow ?? this.cardShadow, primary: primary ?? this.primary, danger: danger ?? this.danger, warning: warning ?? this.warning, success: success ?? this.success, ); } @override AppColors lerp(AppColors? other, double t) { if (other == null) return this; return AppColors( pageBackground: Color.lerp(pageBackground, other.pageBackground, t)!, cardBackground: Color.lerp(cardBackground, other.cardBackground, t)!, fillBackground: Color.lerp(fillBackground, other.fillBackground, t)!, textPrimary: Color.lerp(textPrimary, other.textPrimary, t)!, textSecondary: Color.lerp(textSecondary, other.textSecondary, t)!, textTertiary: Color.lerp(textTertiary, other.textTertiary, t)!, divider: Color.lerp(divider, other.divider, t)!, cardShadow: Color.lerp(cardShadow, other.cardShadow, t)!, primary: Color.lerp(primary, other.primary, t)!, danger: Color.lerp(danger, other.danger, t)!, warning: Color.lerp(warning, other.warning, t)!, success: Color.lerp(success, other.success, t)!, ); } } /// 便捷访问扩展:`context.appColors` extension AppColorsX on BuildContext { AppColors get appColors => Theme.of(this).extension()!; } class AppTheme { // 基础色值定义 static const Color _pureWhite = Color(0xFFFFFFFF); static const Color _offWhite = Color(0xFFfafafc); // 稍微带点灰的白,用于背景增加层次感 static const Color _pureBlack = Color(0xFF000000); static const Color _darkGrey = Color(0xFF1C1C1E); // iOS 风格的深灰黑色 static const Color _surfaceDark = Color(0xFF2C2C2E); // 深色模式下卡片、弹窗表面色 static ThemeData get lightTheme { return ThemeData( useMaterial3: true, brightness: Brightness.light, fontFamily: (Platform.isWindows) ? 'Microsoft YaHei' : null, // 语义色扩展 extensions: const [AppColors.light], // 1. 整体背景色 scaffoldBackgroundColor: _offWhite, // 2. 核心颜色方案 colorScheme: const ColorScheme.light( primary: _pureBlack, // 主色设为黑色 onPrimary: _pureWhite, // 黑色背景上的文字设为白色 surface: _pureWhite, // 卡片、弹窗等表面颜色 onSurface: _pureBlack, // 表面上的文字色 background: _offWhite, ), // 3. 全局按钮主题 elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: _pureBlack, foregroundColor: _pureWhite, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), ), ), // 4. 填充按钮主题 (常用语 Material 3) filledButtonTheme: FilledButtonThemeData( style: FilledButton.styleFrom( backgroundColor: _pureBlack, foregroundColor: _pureWhite, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), // 5. AppBar 主题 (纯白背景,黑色文字) appBarTheme: const AppBarTheme( backgroundColor: _pureWhite, surfaceTintColor: Colors.transparent, elevation: 0, centerTitle: true, iconTheme: IconThemeData(color: _pureBlack), titleTextStyle: TextStyle( color: _pureBlack, fontSize: 18, fontWeight: FontWeight.w700, letterSpacing: -0.5, ), ), // 6. 输入框主题 (黑白简约) inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: _pureWhite, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Colors.black12), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Colors.black12), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: _pureBlack, width: 1.5), ), ), ); } /// 深色主题 (与浅色主题对称的黑白简约风格) static ThemeData get darkTheme { return ThemeData( useMaterial3: true, brightness: Brightness.dark, fontFamily: (Platform.isWindows) ? 'Microsoft YaHei' : null, // 语义色扩展 extensions: const [AppColors.dark], // 1. 整体背景色 (iOS 风格深灰黑) scaffoldBackgroundColor: _darkGrey, // 2. 核心颜色方案 (与浅色主题反色:主色白色) colorScheme: const ColorScheme.dark( primary: _pureWhite, // 主色设为白色 onPrimary: _pureBlack, // 白色背景上的文字设为黑色 surface: _surfaceDark, // 卡片、弹窗等表面颜色 onSurface: _pureWhite, // 表面上的文字色 ), // 3. 全局按钮主题 (白底黑字) elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( backgroundColor: _pureWhite, foregroundColor: _pureBlack, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), ), ), // 4. 填充按钮主题 (常用语 Material 3) filledButtonTheme: FilledButtonThemeData( style: FilledButton.styleFrom( backgroundColor: _pureWhite, foregroundColor: _pureBlack, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), // 5. AppBar 主题 (深灰黑背景,白色文字) appBarTheme: const AppBarTheme( backgroundColor: _darkGrey, surfaceTintColor: Colors.transparent, elevation: 0, centerTitle: true, iconTheme: IconThemeData(color: _pureWhite), titleTextStyle: TextStyle( color: _pureWhite, fontSize: 18, fontWeight: FontWeight.w700, letterSpacing: -0.5, ), ), // 6. 输入框主题 (深色填充,白色边框) inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: _surfaceDark, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Colors.white12), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Colors.white12), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: _pureWhite, width: 1.5), ), ), ); } }