# AISee Flutter 项目初始化指南 ## 1. 创建项目 ```bash cd C:\Users\xdedmi\Desktop\aisee # 创建 Flutter 项目 flutter create --org com.aisee --project-name aisee_app --platforms android,ios aisee_app cd aisee_app ``` ## 2. 项目目录结构 ``` aisee_app/ ├── lib/ │ ├── main.dart # 入口文件 │ ├── app.dart # App 根组件 │ │ │ ├── config/ # 配置 │ │ ├── app_config.dart # 应用配置 │ │ ├── routes.dart # 路由配置 │ │ └── theme.dart # 主题配置 │ │ │ ├── models/ # 数据模型 │ │ ├── detection.dart # 检测结果 │ │ ├── text_region.dart # 文字区域 │ │ ├── scene_description.dart # 场景描述 │ │ └── analysis_result.dart # 分析结果 │ │ │ ├── services/ # 服务层 │ │ ├── api/ │ │ │ ├── api_client.dart # HTTP 客户端 │ │ │ ├── image_api.dart # 图像 API │ │ │ └── analysis_api.dart # 分析 API │ │ ├── bluetooth/ │ │ │ ├── bluetooth_service.dart # 蓝牙服务 │ │ │ └── glasses_protocol.dart # 眼镜通信协议 │ │ ├── camera/ │ │ │ └── camera_service.dart # 相机服务 │ │ ├── websocket/ │ │ │ └── ws_service.dart # WebSocket 服务 │ │ └── tts/ │ │ └── tts_service.dart # 语音合成服务 │ │ │ ├── providers/ # 状态管理 │ │ ├── camera_provider.dart │ │ ├── analysis_provider.dart │ │ ├── bluetooth_provider.dart │ │ └── settings_provider.dart │ │ │ ├── screens/ # 页面 │ │ ├── home/ │ │ │ └── home_screen.dart │ │ ├── camera/ │ │ │ └── camera_screen.dart │ │ ├── analysis/ │ │ │ └── analysis_screen.dart │ │ ├── history/ │ │ │ └── history_screen.dart │ │ ├── settings/ │ │ │ └── settings_screen.dart │ │ └── bluetooth/ │ │ └── bluetooth_screen.dart │ │ │ ├── widgets/ # 通用组件 │ │ ├── detection_overlay.dart # 检测结果叠加层 │ │ ├── loading_indicator.dart │ │ └── error_widget.dart │ │ │ └── utils/ # 工具类 │ ├── constants.dart │ ├── image_utils.dart │ └── permission_utils.dart │ ├── assets/ # 静态资源 │ ├── images/ │ ├── icons/ │ └── fonts/ │ ├── test/ # 测试 │ ├── services/ │ ├── providers/ │ └── widgets/ │ ├── android/ # Android 原生代码 ├── ios/ # iOS 原生代码 ├── pubspec.yaml # 依赖配置 └── analysis_options.yaml # 代码分析配置 ``` ## 3. 依赖配置 pubspec.yaml ```yaml name: aisee_app description: AISee - AI 视觉辅助眼镜系统 publish_to: 'none' version: 0.1.0+1 environment: sdk: '>=3.2.0 <4.0.0' dependencies: flutter: sdk: flutter # UI cupertino_icons: ^1.0.6 google_fonts: ^6.1.0 flutter_svg: ^2.0.9 cached_network_image: ^3.3.0 shimmer: ^3.0.0 # 状态管理 riverpod: ^2.4.9 flutter_riverpod: ^2.4.9 # 路由 go_router: ^13.0.0 # 网络 dio: ^5.4.0 web_socket_channel: ^2.4.0 # 相机 camera: ^0.10.5+7 image: ^4.1.4 # 蓝牙 flutter_blue_plus: ^1.28.5 # 本地存储 sqflite: ^2.3.0 shared_preferences: ^2.2.2 path_provider: ^2.1.1 hive: ^2.2.3 hive_flutter: ^1.1.0 # 权限 permission_handler: ^11.1.0 # 语音 flutter_tts: ^3.8.5 # 图像处理 image_picker: ^1.0.5 # JSON 序列化 json_annotation: ^4.8.1 freezed_annotation: ^2.4.1 # 工具 logger: ^2.0.2+1 intl: ^0.19.0 uuid: ^4.2.1 connectivity_plus: ^5.0.2 dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^3.0.1 # 代码生成 build_runner: ^2.4.7 json_serializable: ^6.7.1 freezed: ^2.4.5 hive_generator: ^2.0.1 # 测试 mockito: ^5.4.3 mocktail: ^1.0.1 flutter: uses-material-design: true assets: - assets/images/ - assets/icons/ fonts: - family: AISee fonts: - asset: assets/fonts/AISee-Regular.ttf - asset: assets/fonts/AISee-Bold.ttf weight: 700 ``` ## 4. 核心代码 ### main.dart ```dart import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'app.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); // 强制竖屏 await SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, ]); // 初始化 Hive 本地存储 await Hive.initFlutter(); runApp( const ProviderScope( child: AISeeApp(), ), ); } ``` ### app.dart ```dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'config/routes.dart'; import 'config/theme.dart'; class AISeeApp extends ConsumerWidget { const AISeeApp({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final router = ref.watch(routerProvider); return MaterialApp.router( title: 'AISee', theme: AISeeTheme.lightTheme, darkTheme: AISeeTheme.darkTheme, themeMode: ThemeMode.system, routerConfig: router, debugShowCheckedModeBanner: false, ); } } ``` ### config/theme.dart ```dart import 'package:flutter/material.dart'; class AISeeTheme { static const _primaryColor = Color(0xFF2196F3); static const _secondaryColor = Color(0xFF00BCD4); static ThemeData get lightTheme { return ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed( seedColor: _primaryColor, secondary: _secondaryColor, brightness: Brightness.light, ), appBarTheme: const AppBarTheme( centerTitle: true, elevation: 0, ), ); } static ThemeData get darkTheme { return ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed( seedColor: _primaryColor, secondary: _secondaryColor, brightness: Brightness.dark, ), appBarTheme: const AppBarTheme( centerTitle: true, elevation: 0, ), ); } } ``` ### config/routes.dart ```dart import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../screens/home/home_screen.dart'; import '../screens/camera/camera_screen.dart'; import '../screens/analysis/analysis_screen.dart'; import '../screens/history/history_screen.dart'; import '../screens/settings/settings_screen.dart'; import '../screens/bluetooth/bluetooth_screen.dart'; final routerProvider = Provider((ref) { return GoRouter( initialLocation: '/', routes: [ GoRoute( path: '/', builder: (context, state) => const HomeScreen(), ), GoRoute( path: '/camera', builder: (context, state) => const CameraScreen(), ), GoRoute( path: '/analysis', builder: (context, state) => const AnalysisScreen(), ), GoRoute( path: '/history', builder: (context, state) => const HistoryScreen(), ), GoRoute( path: '/settings', builder: (context, state) => const SettingsScreen(), ), GoRoute( path: '/bluetooth', builder: (context, state) => const BluetoothScreen(), ), ], ); }); ``` ### config/app_config.dart ```dart class AppConfig { // API 配置 static const String apiBaseUrl = 'https://api.aisee.com'; static const String wsBaseUrl = 'wss://api.aisee.com/ws'; // 开发环境 static const String devApiBaseUrl = 'http://10.0.2.2:8000'; static const String devWsBaseUrl = 'ws://10.0.2.2:8000/ws'; // 图像配置 static const int imageMaxWidth = 1280; static const int imageMaxHeight = 720; static const int imageQuality = 85; // 蓝牙配置 static const String glassesServiceUuid = '0000ffe0-0000-1000-8000-00805f9b34fb'; static const String glassesCharUuid = '0000ffe1-0000-1000-8000-00805f9b34fb'; // 超时配置 static const Duration apiTimeout = Duration(seconds: 30); static const Duration wsReconnectDelay = Duration(seconds: 5); } ``` ### services/api/api_client.dart ```dart import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../config/app_config.dart'; final apiClientProvider = Provider((ref) { return ApiClient(); }); class ApiClient { late final Dio _dio; ApiClient() { _dio = Dio(BaseOptions( baseUrl: AppConfig.devApiBaseUrl, connectTimeout: AppConfig.apiTimeout, receiveTimeout: AppConfig.apiTimeout, headers: { 'Content-Type': 'application/json', }, )); _dio.interceptors.add(LogInterceptor( requestBody: true, responseBody: true, )); } // 上传图像 Future> uploadImage(List imageBytes, String filename) async { final formData = FormData.fromMap({ 'file': MultipartFile.fromBytes(imageBytes, filename: filename), }); final response = await _dio.post('/api/v1/images/upload', data: formData); return response.data; } // 请求 AI 分析 Future> analyzeImage(String imageUrl) async { final response = await _dio.post('/api/v1/analysis/analyze', data: { 'image_url': imageUrl, }); return response.data; } } ``` ### services/camera/camera_service.dart ```dart import 'package:camera/camera.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logger/logger.dart'; final cameraServiceProvider = Provider((ref) { return CameraService(); }); class CameraService { final _logger = Logger(); CameraController? _controller; List _cameras = []; CameraController? get controller => _controller; bool get isInitialized => _controller?.value.isInitialized ?? false; Future initialize() async { _cameras = await availableCameras(); if (_cameras.isEmpty) { _logger.e('No cameras available'); return; } _controller = CameraController( _cameras.first, ResolutionPreset.medium, enableAudio: false, imageFormatGroup: ImageFormatGroup.jpeg, ); await _controller!.initialize(); _logger.i('Camera initialized'); } Future takePicture() async { if (!isInitialized) return null; return await _controller!.takePicture(); } void dispose() { _controller?.dispose(); } } ``` ### services/bluetooth/bluetooth_service.dart ```dart import 'dart:async'; import 'dart:convert'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logger/logger.dart'; import '../../config/app_config.dart'; final bluetoothServiceProvider = Provider((ref) { return BluetoothService(); }); class BluetoothService { final _logger = Logger(); BluetoothDevice? _connectedDevice; BluetoothCharacteristic? _writeCharacteristic; final _dataController = StreamController>.broadcast(); Stream> get dataStream => _dataController.stream; bool get isConnected => _connectedDevice != null; // 扫描设备 Future> scanDevices({Duration timeout = const Duration(seconds: 5)}) async { final results = []; await FlutterBluePlus.startScan(timeout: timeout); FlutterBluePlus.scanResults.listen((scanResults) { results.addAll(scanResults); }); await Future.delayed(timeout); await FlutterBluePlus.stopScan(); return results; } // 连接设备 Future connect(BluetoothDevice device) async { try { await device.connect(timeout: const Duration(seconds: 10)); _connectedDevice = device; // 发现服务 final services = await device.discoverServices(); for (var service in services) { if (service.uuid.toString() == AppConfig.glassesServiceUuid) { for (var char in service.characteristics) { if (char.uuid.toString() == AppConfig.glassesCharUuid) { _writeCharacteristic = char; // 监听数据 await char.setNotifyValue(true); char.onValueReceived.listen((data) { _dataController.add(data); }); } } } } _logger.i('Connected to ${device.platformName}'); return true; } catch (e) { _logger.e('Connection failed: $e'); return false; } } // 发送数据到眼镜 Future sendToGlasses(Map data) async { if (_writeCharacteristic == null) return; final jsonStr = jsonEncode(data); final bytes = utf8.encode(jsonStr); await _writeCharacteristic!.write(bytes); } // 断开连接 Future disconnect() async { await _connectedDevice?.disconnect(); _connectedDevice = null; _writeCharacteristic = null; } void dispose() { _dataController.close(); disconnect(); } } ``` ### screens/home/home_screen.dart ```dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class HomeScreen extends ConsumerWidget { const HomeScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar( title: const Text('AISee'), actions: [ IconButton( icon: const Icon(Icons.bluetooth), onPressed: () => context.push('/bluetooth'), ), IconButton( icon: const Icon(Icons.settings), onPressed: () => context.push('/settings'), ), ], ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 状态卡片 Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ const Icon(Icons.visibility, size: 48, color: Colors.blue), const SizedBox(height: 8), Text( 'AISee 视觉辅助', style: Theme.of(context).textTheme.headlineSmall, ), const SizedBox(height: 4), const Text('眼镜未连接', style: TextStyle(color: Colors.grey)), ], ), ), ), const SizedBox(height: 24), // 功能按钮 Expanded( child: GridView.count( crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, children: [ _FeatureCard( icon: Icons.camera_alt, label: '拍照识别', color: Colors.blue, onTap: () => context.push('/camera'), ), _FeatureCard( icon: Icons.text_fields, label: '文字识别', color: Colors.green, onTap: () => context.push('/camera'), ), _FeatureCard( icon: Icons.landscape, label: '场景理解', color: Colors.orange, onTap: () => context.push('/camera'), ), _FeatureCard( icon: Icons.history, label: '历史记录', color: Colors.purple, onTap: () => context.push('/history'), ), ], ), ), ], ), ), ); } } class _FeatureCard extends StatelessWidget { final IconData icon; final String label; final Color color; final VoidCallback onTap; const _FeatureCard({ required this.icon, required this.label, required this.color, required this.onTap, }); @override Widget build(BuildContext context) { return Card( elevation: 2, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, size: 48, color: color), const SizedBox(height: 8), Text(label, style: Theme.of(context).textTheme.titleMedium), ], ), ), ); } } ``` ### 其他页面占位 ```dart // screens/camera/camera_screen.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class CameraScreen extends ConsumerWidget { const CameraScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar(title: const Text('拍照识别')), body: const Center(child: Text('相机页面 - 待开发')), ); } } // screens/analysis/analysis_screen.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class AnalysisScreen extends ConsumerWidget { const AnalysisScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar(title: const Text('分析结果')), body: const Center(child: Text('分析结果页面 - 待开发')), ); } } // screens/history/history_screen.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class HistoryScreen extends ConsumerWidget { const HistoryScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar(title: const Text('历史记录')), body: const Center(child: Text('历史记录页面 - 待开发')), ); } } // screens/settings/settings_screen.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class SettingsScreen extends ConsumerWidget { const SettingsScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar(title: const Text('设置')), body: const Center(child: Text('设置页面 - 待开发')), ); } } // screens/bluetooth/bluetooth_screen.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class BluetoothScreen extends ConsumerWidget { const BluetoothScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar(title: const Text('蓝牙连接')), body: const Center(child: Text('蓝牙连接页面 - 待开发')), ); } } ``` ## 5. Android 权限配置 ### android/app/src/main/AndroidManifest.xml 添加权限 ```xml ``` ### android/app/build.gradle 修改最低 SDK ```groovy android { defaultConfig { minSdkVersion 21 // 改为 21 } } ``` ## 6. 初始化项目命令 ```bash # 1. 创建项目 cd C:\Users\xdedmi\Desktop\aisee flutter create --org com.aisee --project-name aisee_app --platforms android,ios aisee_app cd aisee_app # 2. 获取依赖 flutter pub get # 3. 运行代码生成(freezed、json_serializable) dart run build_runner build --delete-conflicting-outputs # 4. 运行项目 flutter run # 5. 运行测试 flutter test ``` ## 7. Git 初始化 ```bash cd C:\Users\xdedmi\Desktop\aisee\aisee_app git init git add . git commit -m "feat: 初始化 AISee Flutter 项目" ``` ## 8. 开发顺序建议 ``` 第 1 周:项目搭建 + 首页 UI 第 2 周:相机模块 + 拍照功能 第 3 周:API 对接 + 图像上传 第 4 周:AI 分析结果展示 第 5 周:蓝牙通信模块 第 6 周:语音播报 + 历史记录 第 7 周:设置页面 + 优化 第 8 周:测试 + Bug 修复 ``` --- **提示**:先运行 `flutter pub get` 安装依赖,然后按照目录结构创建文件,逐步填充代码。