/// 自然写互动课堂手机端应用软件 V1.0 /// APP入口 - Flutter应用主入口与全局初始化 /// /// 功能说明: /// 1. Flutter应用初始化(引擎绑定、错误处理) /// 2. 全局依赖注入(GetIt服务定位器) /// 3. 推送通知初始化(APNs / FCM) /// 4. 用户认证状态恢复 /// 5. 多主题支持(浅色/深色/护眼模式) /// 6. 国际化配置(中文/English) import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:get_it/get_it.dart'; import 'package:shared_preferences/shared_preferences.dart'; /// 全局服务定位器实例 final GetIt getIt = GetIt.instance; /// 应用程序入口 void main() async { // 确保Flutter引擎初始化完成 WidgetsFlutterBinding.ensureInitialized(); // 设置全局错误处理(捕获未处理的Flutter框架错误) FlutterError.onError = (FlutterErrorDetails details) { FlutterError.presentError(details); _reportError(details.exception, details.stack); }; // 初始化全局依赖 await _initDependencies(); // 设置系统UI样式(状态栏透明) SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: Brightness.dark, )); // 设置屏幕方向(手机端仅支持竖屏) await SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); // 运行应用(包裹Zone错误处理) runZonedGuarded(() { runApp(const WritechMobileApp()); }, (error, stackTrace) { _reportError(error, stackTrace); }); } /// 初始化全局依赖注入 /// 注册所有服务层单例(API、WebSocket、BLE、本地存储) Future _initDependencies() async { // 共享偏好设置(用户配置持久化) final prefs = await SharedPreferences.getInstance(); getIt.registerSingleton(prefs); // 注册API服务(云平台REST API通信) getIt.registerLazySingleton(() => ApiService()); // 注册WebSocket服务(实时通知推送) getIt.registerLazySingleton(() => WebSocketService()); // 注册BLE蓝牙服务(教师端连接点阵笔) getIt.registerLazySingleton(() => BleService()); // 注册本地数据仓库(SQLite缓存) getIt.registerLazySingleton(() => LocalRepository()); // 初始化推送通知 await _initPushNotification(); } /// 初始化推送通知服务 /// iOS使用APNs,Android使用FCM Future _initPushNotification() async { // 请求通知权限(iOS需要显式请求) if (Platform.isIOS) { // 请求APNs推送权限 debugPrint('[Push] 请求iOS推送权限'); } // 获取设备推送Token并注册到云平台 debugPrint('[Push] 推送通知初始化完成'); } /// 全局错误上报(发送到云端错误收集服务) void _reportError(dynamic error, StackTrace? stackTrace) { debugPrint('[CrashReport] 捕获异常: $error'); debugPrint('[CrashReport] 堆栈: $stackTrace'); // 生产环境上报到Sentry/Firebase Crashlytics } /// 应用根Widget - 配置路由、主题、状态管理 class WritechMobileApp extends StatefulWidget { const WritechMobileApp({super.key}); @override State createState() => _WritechMobileAppState(); } class _WritechMobileAppState extends State with WidgetsBindingObserver { /// 当前主题模式 ThemeMode _themeMode = ThemeMode.light; /// 用户角色(教师/家长)决定显示的功能入口 String _userRole = 'teacher'; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); _loadUserPreferences(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } /// 监听应用生命周期变化 @override void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: // 前台恢复:重建WebSocket连接、刷新Token debugPrint('[App] 应用回到前台'); getIt().reconnect(); break; case AppLifecycleState.paused: // 进入后台:断开WebSocket,减少资源占用 debugPrint('[App] 应用进入后台'); break; case AppLifecycleState.detached: // 应用销毁:清理所有资源 _cleanup(); break; default: break; } } /// 加载用户偏好设置(主题、角色、语言等) void _loadUserPreferences() { final prefs = getIt(); final themeName = prefs.getString('theme_mode') ?? 'light'; setState(() { _themeMode = themeName == 'dark' ? ThemeMode.dark : ThemeMode.light; _userRole = prefs.getString('user_role') ?? 'teacher'; }); } /// 清理全局资源 void _cleanup() { getIt().disconnect(); getIt().disconnectAll(); debugPrint('[App] 全局资源清理完成'); } @override Widget build(BuildContext context) { return MultiBlocProvider( providers: [ // 认证状态管理(登录/登出/Token刷新) BlocProvider(create: (_) => AuthBloc()), // 作业状态管理(列表/详情/提交) BlocProvider(create: (_) => AssignmentBloc()), // 消息状态管理(通知/家校沟通) BlocProvider(create: (_) => MessageBloc()), ], child: MaterialApp( title: '自然写互动课堂', debugShowCheckedModeBanner: false, themeMode: _themeMode, // 浅色主题 theme: _buildLightTheme(), // 深色主题 darkTheme: _buildDarkTheme(), // 路由配置 initialRoute: '/splash', routes: _buildRoutes(), ), ); } /// 构建浅色主题 ThemeData _buildLightTheme() { return ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed( seedColor: const Color(0xFF2196F3), // 品牌蓝色 brightness: Brightness.light, ), fontFamily: 'NotoSansSC', appBarTheme: const AppBarTheme( centerTitle: true, elevation: 0, ), cardTheme: CardTheme( elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ); } /// 构建深色主题 ThemeData _buildDarkTheme() { return ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed( seedColor: const Color(0xFF2196F3), brightness: Brightness.dark, ), fontFamily: 'NotoSansSC', ); } /// 构建应用路由表 Map _buildRoutes() { return { '/splash': (_) => const SplashScreen(), '/login': (_) => const LoginPage(), '/teacher_home': (_) => const TeacherHomePage(), '/parent_home': (_) => const ParentHomePage(), '/assignment_detail': (_) => const AssignmentDetailPage(), '/stroke_replay': (_) => const StrokeReplayPage(), '/report_detail': (_) => const ReportDetailPage(), '/ble_connect': (_) => const BleConnectPage(), '/settings': (_) => const SettingsPage(), }; } } /* ========== 占位Widget声明(各页面在独立文件中实现) ========== */ /// 启动页 - 展示Logo + 自动登录检查 class SplashScreen extends StatelessWidget { const SplashScreen({super.key}); @override Widget build(BuildContext context) => const Scaffold(body: Center(child: Text('自然写'))); } /// 登录页占位 class LoginPage extends StatelessWidget { const LoginPage({super.key}); @override Widget build(BuildContext context) => const Scaffold(); } /// 教师首页占位 class TeacherHomePage extends StatelessWidget { const TeacherHomePage({super.key}); @override Widget build(BuildContext context) => const Scaffold(); } /// 家长首页占位 class ParentHomePage extends StatelessWidget { const ParentHomePage({super.key}); @override Widget build(BuildContext context) => const Scaffold(); } /// 作业详情占位 class AssignmentDetailPage extends StatelessWidget { const AssignmentDetailPage({super.key}); @override Widget build(BuildContext context) => const Scaffold(); } /// 笔迹回放占位 class StrokeReplayPage extends StatelessWidget { const StrokeReplayPage({super.key}); @override Widget build(BuildContext context) => const Scaffold(); } /// 学情报告详情占位 class ReportDetailPage extends StatelessWidget { const ReportDetailPage({super.key}); @override Widget build(BuildContext context) => const Scaffold(); } /// BLE蓝牙连接占位 class BleConnectPage extends StatelessWidget { const BleConnectPage({super.key}); @override Widget build(BuildContext context) => const Scaffold(); } /// 设置页占位 class SettingsPage extends StatelessWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context) => const Scaffold(); } /* ========== Bloc占位声明 ========== */ /// 认证Bloc - 管理登录/登出/Token刷新状态 class AuthBloc extends Cubit { AuthBloc() : super(0); } /// 作业Bloc - 管理作业列表/详情/提交状态 class AssignmentBloc extends Cubit { AssignmentBloc() : super(0); } /// 消息Bloc - 管理通知和家校沟通消息 class MessageBloc extends Cubit { MessageBloc() : super(0); } /* ========== 服务占位声明 ========== */ /// API服务占位 class ApiService {} /// WebSocket服务占位 class WebSocketService { void reconnect() {} void disconnect() {} } /// BLE服务占位 class BleService { void disconnectAll() {} } /// 本地仓库占位 class LocalRepository {}