chore: 初始化脚手架 — sunny_mochi 企业级 Flutter 模板

Core 基础设施:Flavor 三包体系、Drift+SQLCipher 加密数据库
7 拦截器 Dio 网络栈、CrashReporter 崩溃日志、Sealed Failure 错误体系
5 色板主题系统、Auth 认证骨架(Clean Architecture)、Dev Panel、Mock Adapter

通过验证:flutter analyze(0 errors)、flutter test(全绿)、staging APK 74.8MB
This commit is contained in:
SkyJourney
2026-05-14 12:51:05 +08:00
commit 61017f1c39
204 changed files with 15386 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:sunny_mochi/core/theme/app_colors.dart';
/// 应用主题工厂 — 按 [AppColorScheme] 真实切换全部色(对齐 iOS 4 套 plist)。
///
/// 与旧版差异:
/// - 旧版只把 primary 当作 seednav/btn/bg 都写死,导致 4 套主题视觉差异不明显
/// - 新版从 [AppPalettes] 读完整 10 色,AppBar/ColorScheme/extensions 全部按主题切
/// - 通过 ThemeExtension 暴露 [AppPalette],业务代码 `Theme.of(context).extension<AppPalette>()!.buttonBg` 读
abstract class AppTheme {
static ThemeData light({AppColorScheme scheme = AppColorScheme.white}) {
final palette = AppPalettes.of(scheme);
return ThemeData(
useMaterial3: true,
// BackButton 图标:iOS 平台渲染 arrow_back_ios_new< 样式),与登录页一致。
// ScrollBehavior 使用 defaultTargetPlatform,不受此字段影响。
platform: TargetPlatform.iOS,
// 全局字体 — HarmonyOS Sans SCGB2312 子集,pubspec 注册)
fontFamily: 'HarmonyOS Sans SC',
colorScheme: ColorScheme.fromSeed(
seedColor: palette.primary,
primary: palette.primary,
secondary: palette.secondary,
surface: AppColors.surface,
error: AppColors.error,
),
scaffoldBackgroundColor: palette.background,
primaryColor: palette.primary,
appBarTheme: AppBarTheme(
backgroundColor: palette.navBar,
foregroundColor: palette.navBarText,
elevation: 0,
// Material 3 默认会在滚动时给 AppBar 叠加 surfaceTint 染色(紫色);
// 设计稿要求 navBar 保持纯白,必须显式置为 transparent + 0 elevation。
surfaceTintColor: Colors.transparent,
scrolledUnderElevation: 0,
centerTitle: true,
titleTextStyle: TextStyle(
color: palette.navBarText,
fontSize: 18.sp,
fontWeight: FontWeight.w600,
),
iconTheme: IconThemeData(color: palette.navBarText, size: 22.sp),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: palette.buttonBg,
foregroundColor: palette.buttonText,
),
),
filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom(
backgroundColor: palette.buttonBg,
foregroundColor: palette.buttonText,
),
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(foregroundColor: palette.primary),
),
tabBarTheme: TabBarThemeData(
labelColor: palette.tabBarSelected,
unselectedLabelColor: palette.tabBarNormal,
indicatorColor: palette.tabBarSelected,
),
bottomNavigationBarTheme: BottomNavigationBarThemeData(
selectedItemColor: palette.tabBarSelected,
unselectedItemColor: palette.tabBarNormal,
),
textTheme: TextTheme(
bodyLarge: TextStyle(fontSize: 16.sp, color: palette.text),
bodyMedium: TextStyle(fontSize: 14.sp, color: AppColors.textSecondary),
bodySmall: TextStyle(fontSize: 12.sp, color: AppColors.textHint),
titleLarge: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: palette.text,
),
),
dividerColor: AppColors.divider,
dividerTheme: const DividerThemeData(space: 1, thickness: 1),
extensions: [palette],
);
}
static ThemeData dark({AppColorScheme scheme = AppColorScheme.white}) {
final palette = AppPalettes.of(scheme);
return ThemeData(
useMaterial3: true,
platform: TargetPlatform.iOS,
brightness: Brightness.dark,
colorScheme: ColorScheme.fromSeed(
seedColor: palette.primary,
primary: palette.primary,
secondary: palette.secondary,
brightness: Brightness.dark,
),
primaryColor: palette.primary,
scaffoldBackgroundColor: const Color(0xFF121212),
appBarTheme: AppBarTheme(
backgroundColor: AppColors.navBarDark,
foregroundColor: Colors.white,
elevation: 0,
centerTitle: true,
titleTextStyle: TextStyle(
color: Colors.white,
fontSize: 17.sp,
fontWeight: FontWeight.w600,
),
),
bottomNavigationBarTheme: BottomNavigationBarThemeData(
selectedItemColor: palette.tabBarSelected,
unselectedItemColor: palette.tabBarNormal,
),
extensions: [palette],
);
}
}