first commit
This commit is contained in:
836
技术文档/Flutter项目初始化.md
Normal file
836
技术文档/Flutter项目初始化.md
Normal file
@@ -0,0 +1,836 @@
|
||||
# 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<GoRouter>((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<ApiClient>((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<Map<String, dynamic>> uploadImage(List<int> 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<Map<String, dynamic>> 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<CameraService>((ref) {
|
||||
return CameraService();
|
||||
});
|
||||
|
||||
class CameraService {
|
||||
final _logger = Logger();
|
||||
CameraController? _controller;
|
||||
List<CameraDescription> _cameras = [];
|
||||
|
||||
CameraController? get controller => _controller;
|
||||
bool get isInitialized => _controller?.value.isInitialized ?? false;
|
||||
|
||||
Future<void> 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<XFile?> 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<BluetoothService>((ref) {
|
||||
return BluetoothService();
|
||||
});
|
||||
|
||||
class BluetoothService {
|
||||
final _logger = Logger();
|
||||
BluetoothDevice? _connectedDevice;
|
||||
BluetoothCharacteristic? _writeCharacteristic;
|
||||
final _dataController = StreamController<List<int>>.broadcast();
|
||||
|
||||
Stream<List<int>> get dataStream => _dataController.stream;
|
||||
bool get isConnected => _connectedDevice != null;
|
||||
|
||||
// 扫描设备
|
||||
Future<List<ScanResult>> scanDevices({Duration timeout = const Duration(seconds: 5)}) async {
|
||||
final results = <ScanResult>[];
|
||||
|
||||
await FlutterBluePlus.startScan(timeout: timeout);
|
||||
FlutterBluePlus.scanResults.listen((scanResults) {
|
||||
results.addAll(scanResults);
|
||||
});
|
||||
|
||||
await Future.delayed(timeout);
|
||||
await FlutterBluePlus.stopScan();
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// 连接设备
|
||||
Future<bool> 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<void> sendToGlasses(Map<String, dynamic> data) async {
|
||||
if (_writeCharacteristic == null) return;
|
||||
|
||||
final jsonStr = jsonEncode(data);
|
||||
final bytes = utf8.encode(jsonStr);
|
||||
await _writeCharacteristic!.write(bytes);
|
||||
}
|
||||
|
||||
// 断开连接
|
||||
Future<void> 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
|
||||
<!-- 在 <manifest> 标签内添加 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="true" />
|
||||
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
||||
```
|
||||
|
||||
### 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` 安装依赖,然后按照目录结构创建文件,逐步填充代码。
|
||||
Reference in New Issue
Block a user