software copyright

This commit is contained in:
jiahong
2026-03-22 15:24:40 +08:00
parent e303bb868a
commit 60f336e345
155 changed files with 127262 additions and 0 deletions
@@ -0,0 +1,340 @@
/// 自然写互动课堂手机端应用软件 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<void> _initDependencies() async {
// 共享偏好设置(用户配置持久化)
final prefs = await SharedPreferences.getInstance();
getIt.registerSingleton<SharedPreferences>(prefs);
// 注册API服务(云平台REST API通信)
getIt.registerLazySingleton<ApiService>(() => ApiService());
// 注册WebSocket服务(实时通知推送)
getIt.registerLazySingleton<WebSocketService>(() => WebSocketService());
// 注册BLE蓝牙服务(教师端连接点阵笔)
getIt.registerLazySingleton<BleService>(() => BleService());
// 注册本地数据仓库(SQLite缓存)
getIt.registerLazySingleton<LocalRepository>(() => LocalRepository());
// 初始化推送通知
await _initPushNotification();
}
/// 初始化推送通知服务
/// iOS使用APNsAndroid使用FCM
Future<void> _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<WritechMobileApp> createState() => _WritechMobileAppState();
}
class _WritechMobileAppState extends State<WritechMobileApp>
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<WebSocketService>().reconnect();
break;
case AppLifecycleState.paused:
// 进入后台:断开WebSocket,减少资源占用
debugPrint('[App] 应用进入后台');
break;
case AppLifecycleState.detached:
// 应用销毁:清理所有资源
_cleanup();
break;
default:
break;
}
}
/// 加载用户偏好设置(主题、角色、语言等)
void _loadUserPreferences() {
final prefs = getIt<SharedPreferences>();
final themeName = prefs.getString('theme_mode') ?? 'light';
setState(() {
_themeMode = themeName == 'dark' ? ThemeMode.dark : ThemeMode.light;
_userRole = prefs.getString('user_role') ?? 'teacher';
});
}
/// 清理全局资源
void _cleanup() {
getIt<WebSocketService>().disconnect();
getIt<BleService>().disconnectAll();
debugPrint('[App] 全局资源清理完成');
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
// 认证状态管理(登录/登出/Token刷新)
BlocProvider<AuthBloc>(create: (_) => AuthBloc()),
// 作业状态管理(列表/详情/提交)
BlocProvider<AssignmentBloc>(create: (_) => AssignmentBloc()),
// 消息状态管理(通知/家校沟通)
BlocProvider<MessageBloc>(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<String, WidgetBuilder> _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<int> {
AuthBloc() : super(0);
}
/// 作业Bloc - 管理作业列表/详情/提交状态
class AssignmentBloc extends Cubit<int> {
AssignmentBloc() : super(0);
}
/// 消息Bloc - 管理通知和家校沟通消息
class MessageBloc extends Cubit<int> {
MessageBloc() : super(0);
}
/* ========== 服务占位声明 ========== */
/// API服务占位
class ApiService {}
/// WebSocket服务占位
class WebSocketService {
void reconnect() {}
void disconnect() {}
}
/// BLE服务占位
class BleService {
void disconnectAll() {}
}
/// 本地仓库占位
class LocalRepository {}