diff --git a/airhub_app/lib/features/badge/presentation/controllers/badge_transfer_controller.dart b/airhub_app/lib/features/badge/presentation/controllers/badge_transfer_controller.dart index c0f7c57..194220b 100644 --- a/airhub_app/lib/features/badge/presentation/controllers/badge_transfer_controller.dart +++ b/airhub_app/lib/features/badge/presentation/controllers/badge_transfer_controller.dart @@ -46,7 +46,11 @@ class BadgeTransferController extends _$BadgeTransferController { void startScan() { if (!ref.mounted) return; state = state.copyWith(status: TransferStatus.scanning); - FlutterBluePlus.startScan(timeout: const Duration(seconds: 10)); + FlutterBluePlus.startScan(timeout: const Duration(seconds: 10)).catchError((e) { + // Web 平台: 用户取消 requestDevice() 选择器会抛出异常 + if (!ref.mounted) return; + state = state.copyWith(status: TransferStatus.idle); + }); FlutterBluePlus.scanResults.listen((results) { if (!ref.mounted) return; diff --git a/airhub_app/lib/features/badge/presentation/pages/badge_home_page.dart b/airhub_app/lib/features/badge/presentation/pages/badge_home_page.dart index 57620cc..c795d5b 100644 --- a/airhub_app/lib/features/badge/presentation/pages/badge_home_page.dart +++ b/airhub_app/lib/features/badge/presentation/pages/badge_home_page.dart @@ -29,7 +29,6 @@ class _BadgeHomePageState extends ConsumerState double _genProgress = 0; String _genStatus = ''; String? _generatedImageUrl; - bool _hasAiResult = false; @override void initState() { @@ -43,7 +42,6 @@ class _BadgeHomePageState extends ConsumerState final pending = BadgeAiGenerationService.instance.consumePendingResult(); if (pending != null) { _generatedImageUrl = pending.imageUrl; - _hasAiResult = true; } // 注册 AI 服务回调 @@ -61,7 +59,6 @@ class _BadgeHomePageState extends ConsumerState setState(() { _isGenerating = false; _generatedImageUrl = result.imageUrl; - _hasAiResult = true; }); _showResultDialog(result.imageUrl); } @@ -213,7 +210,6 @@ class _BadgeHomePageState extends ConsumerState setState(() { _isGenerating = true; _generatedImageUrl = null; - _hasAiResult = false; _genProgress = 0; _genStatus = '正在连接 AI...'; }); @@ -242,7 +238,6 @@ class _BadgeHomePageState extends ConsumerState void _handleRetry() { setState(() { _generatedImageUrl = null; - _hasAiResult = false; }); } @@ -420,31 +415,33 @@ class _BadgeHomePageState extends ConsumerState Widget? buttonContent; if (isAiTab) { - // 有结果时由弹窗处理,底部只显示"开始生成" - if (!_isGenerating && !_hasAiResult) { - buttonContent = _buildGradientButton('开始生成', () { - final aiState = _aiTabKey.currentState; - if (aiState == null) return; - final prompt = aiState.currentPrompt; - final isI2I = aiState.referenceImageBytes != null; - // 文生图必须输入描述,图生图可选 - if (!isI2I && prompt.isEmpty) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('请输入图片描述'), - backgroundColor: Colors.orange, - ), - ); - return; - } - _handleAiGenerate( - prompt: prompt, - style: aiState.selectedStyle, - imageBytes: aiState.referenceImageBytes, - strength: aiState.strength, - ); - }); - } + buttonContent = _buildGradientButton( + '开始生成', + _isGenerating + ? null + : () { + final aiState = _aiTabKey.currentState; + if (aiState == null) return; + final prompt = aiState.currentPrompt; + final isI2I = aiState.referenceImageBytes != null; + // 文生图必须输入描述,图生图可选 + if (!isI2I && prompt.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('请输入图片描述'), + backgroundColor: Colors.orange, + ), + ); + return; + } + _handleAiGenerate( + prompt: prompt, + style: aiState.selectedStyle, + imageBytes: aiState.referenceImageBytes, + strength: aiState.strength, + ); + }, + ); } else if (isUploadTab) { if (_uploadedImagePath != null) { buttonContent = _buildGradientButton('使用此图', _handleUseImage); @@ -474,7 +471,7 @@ class _BadgeHomePageState extends ConsumerState ); } - Widget _buildGradientButton(String label, VoidCallback onPressed) { + Widget _buildGradientButton(String label, VoidCallback? onPressed) { return SizedBox( height: 52, child: DecoratedBox( diff --git a/airhub_app/lib/features/badge/presentation/pages/badge_transfer_page.dart b/airhub_app/lib/features/badge/presentation/pages/badge_transfer_page.dart index 2b29938..6cf0b75 100644 --- a/airhub_app/lib/features/badge/presentation/pages/badge_transfer_page.dart +++ b/airhub_app/lib/features/badge/presentation/pages/badge_transfer_page.dart @@ -45,7 +45,10 @@ class _BadgeTransferPageState extends ConsumerState { } void _startScan() { - FlutterBluePlus.startScan(timeout: const Duration(seconds: 10)); + FlutterBluePlus.startScan(timeout: const Duration(seconds: 10)).catchError((e) { + // Web 平台: 用户取消 requestDevice() 选择器会抛出异常 + debugPrint('[Badge BLE] startScan 异常(用户可能取消了选择器): $e'); + }); } @override diff --git a/airhub_app/lib/pages/bluetooth_page.dart b/airhub_app/lib/pages/bluetooth_page.dart index cd94aae..1da1b51 100644 --- a/airhub_app/lib/pages/bluetooth_page.dart +++ b/airhub_app/lib/pages/bluetooth_page.dart @@ -218,10 +218,19 @@ class _BluetoothPageState extends ConsumerState }); // 持续扫描(不设超时),由 _queryDeviceByMac 成功后停止 - await FlutterBluePlus.startScan( - timeout: const Duration(seconds: 30), - androidUsesFineLocation: true, - ); + try { + await FlutterBluePlus.startScan( + timeout: const Duration(seconds: 30), + androidUsesFineLocation: true, + ); + } catch (e) { + // Web 平台: 用户取消 requestDevice() 选择器会抛出 FlutterBluePlusException + debugPrint('[BLE Scan] startScan 异常(用户可能取消了选择器): $e'); + if (mounted) { + setState(() => _isSearching = false); + } + return; + } // 30 秒兜底超时:如果始终没找到设备 if (mounted && _isSearching) {