import 'package:flutter/material.dart'; import 'package:camera/camera.dart'; import 'package:provider/provider.dart'; import 'package:permission_handler/permission_handler.dart'; import '../services/camera_service.dart'; import '../services/api_service.dart'; class CameraScreen extends StatefulWidget { const CameraScreen({super.key}); @override State createState() => _CameraScreenState(); } class _CameraScreenState extends State { late CameraService _cameraService; late ApiService _apiService; bool _isProcessing = false; String _statusMessage = '准备就绪'; int _frameCount = 0; int _uploadCount = 0; @override void initState() { super.initState(); _cameraService = CameraService(); _apiService = ApiService(); _initializeCamera(); } Future _initializeCamera() async { // 请求相机权限 final status = await Permission.camera.request(); if (!status.isGranted) { setState(() { _statusMessage = '相机权限被拒绝'; }); return; } // 初始化相机 await _cameraService.initialize(); if (mounted) { setState(() { _statusMessage = '相机已就绪'; }); } } /// 开始实时传输 void _startStreaming() { if (_cameraService.isStreaming) return; setState(() { _statusMessage = '实时传输中...'; _frameCount = 0; _uploadCount = 0; }); _cameraService.startStreaming((imageBytes) async { setState(() { _frameCount++; }); // 上传到后端(异步,不阻塞捕获) _uploadToBackend(imageBytes); }); } /// 停止实时传输 void _stopStreaming() { _cameraService.stopStreaming(); setState(() { _statusMessage = '已停止传输'; }); } /// 上传图像到后端 Future _uploadToBackend(imageBytes) async { if (_isProcessing) return; // 防止并发上传 _isProcessing = true; try { // 上传图像 final result = await _apiService.uploadImage(imageBytes); setState(() { _uploadCount++; _statusMessage = '已上传 $_uploadCount 帧'; }); print('上传成功: ${result['image_id']}'); } catch (e) { print('上传失败: $e'); setState(() { _statusMessage = '上传失败: $e'; }); } finally { _isProcessing = false; } } /// 拍摄单张照片并分析 Future _captureAndAnalyze() async { setState(() { _statusMessage = '正在拍照...'; }); final imageBytes = await _cameraService.takePicture(); if (imageBytes == null) { setState(() { _statusMessage = '拍照失败'; }); return; } setState(() { _statusMessage = '正在分析...'; }); try { // 上传并分析 final result = await _apiService.uploadAndAnalyze(imageBytes); setState(() { _statusMessage = '分析完成'; }); // 显示结果 _showAnalysisResult(result); } catch (e) { setState(() { _statusMessage = '分析失败: $e'; }); } } /// 显示分析结果 void _showAnalysisResult(Map result) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('分析结果'), content: SingleChildScrollView( child: Text(result.toString()), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('关闭'), ), ], ), ); } @override void dispose() { _cameraService.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('实时相机'), backgroundColor: Colors.black, ), body: _cameraService.isInitialized ? _buildCameraView() : const Center(child: CircularProgressIndicator()), ); } Widget _buildCameraView() { return Stack( children: [ // 相机预览 Positioned.fill( child: CameraPreview(_cameraService.controller!), ), // 状态信息 Positioned( top: 16, left: 16, right: 16, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.black.withOpacity(0.7), borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _statusMessage, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( '捕获帧数: $_frameCount | 上传帧数: $_uploadCount', style: const TextStyle( color: Colors.white70, fontSize: 14, ), ), ], ), ), ), // 控制按钮 Positioned( bottom: 32, left: 0, right: 0, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // 拍照并分析按钮 _buildControlButton( icon: Icons.camera_alt, label: '拍照分析', onPressed: _captureAndAnalyze, color: Colors.blue, ), // 开始/停止实时传输按钮 _buildControlButton( icon: _cameraService.isStreaming ? Icons.stop : Icons.play_arrow, label: _cameraService.isStreaming ? '停止传输' : '开始传输', onPressed: _cameraService.isStreaming ? _stopStreaming : _startStreaming, color: _cameraService.isStreaming ? Colors.red : Colors.green, ), // 切换摄像头按钮 _buildControlButton( icon: Icons.flip_camera_android, label: '切换', onPressed: () => _cameraService.switchCamera(), color: Colors.orange, ), ], ), ), ], ); } Widget _buildControlButton({ required IconData icon, required String label, required VoidCallback onPressed, required Color color, }) { return Column( mainAxisSize: MainAxisSize.min, children: [ FloatingActionButton( onPressed: onPressed, backgroundColor: color, child: Icon(icon, size: 32), ), const SizedBox(height: 8), Text( label, style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold, shadows: [ Shadow( color: Colors.black, blurRadius: 4, ), ], ), ), ], ); } }