// ignore_for_file: invalid_use_of_protected_member part of '../../registration_page.dart'; extension _RegistrationDialogsPart on _RegistrationPageState { void _showLocationSwitchDialog( String newLocationCode, CodeType newLocationType, ) { final count = _zongpaiNos.length; showDialog( context: context, barrierDismissible: false, builder: (ctx) => AlertDialog( backgroundColor: Colors.orange.shade50, title: Row( children: [ Icon(Icons.warning_amber, color: Colors.orange.shade800), const SizedBox(width: 8), Text('切换货架号', style: TextStyle(color: Colors.orange.shade900)), ], ), content: Text( '当前已有 $count 条待上架数据,切换货架号不会清除已扫描的总排号。', style: const TextStyle(fontSize: 14), ), actions: [ TextButton( onPressed: () { Navigator.pop(ctx); }, child: const Text('取消'), ), ElevatedButton( onPressed: () { Navigator.pop(ctx); _feedbackService.trigger(FeedbackEvent.scanValid); setState(() { _locationCode = newLocationCode; _locationType = newLocationType; _clearStatusOverride(); }); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.orange.shade700, foregroundColor: Colors.white, ), child: const Text('确认切换'), ), ], ), ); } void _showDuplicateDialog(String zongpaiNo, Map? info) { showDialog( context: context, barrierDismissible: false, builder: (ctx) => AlertDialog( backgroundColor: Colors.red.shade50, title: const Row( children: [ Icon(Icons.warning, color: Colors.red), SizedBox(width: 8), Text('重复上架', style: TextStyle(color: Colors.red)), ], ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('总排号:$zongpaiNo'), const SizedBox(height: 4), Text('已登记货位:${info?["location_code"] ?? "未知"}'), const SizedBox(height: 4), Text('登记时间:${info?["registered_at"] ?? "未知"}'), const SizedBox(height: 12), const Text( '请核查实物,确认是否操作错误。', style: TextStyle(fontWeight: FontWeight.bold), ), ], ), actions: [ TextButton( onPressed: () { _feedbackService.stopAlert(); Navigator.pop(ctx); }, child: const Text('关闭'), ), ], ), ); } void _showLocationConflictDialog({ required List onShelfItems, required List transferredItems, }) { final contentParts = []; if (onShelfItems.isNotEmpty) { contentParts.add( Text( '重复上架', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.red.shade700, ), ), ); for (final item in onShelfItems) { contentParts.addAll([ Text('总排号:${item.zongpaiNo}'), Text('已登记货位:${item.locationCode ?? "未知"}'), const SizedBox(height: 6), ]); } } if (transferredItems.isNotEmpty) { if (onShelfItems.isNotEmpty) { contentParts.add(const Divider()); contentParts.add(const SizedBox(height: 4)); } contentParts.add( Text( '货物已转运', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.orange.shade700, ), ), ); for (final item in transferredItems) { contentParts.addAll([ Text('总排号:${item.zongpaiNo}'), Text('转运货位:${item.locationCode ?? "未知"}'), const SizedBox(height: 6), ]); } } contentParts.add(const SizedBox(height: 4)); contentParts.add( const Text( '请核查实物,确认是否操作错误。', style: TextStyle(fontWeight: FontWeight.bold), ), ); showDialog( context: context, barrierDismissible: false, builder: (ctx) => AlertDialog( backgroundColor: Colors.red.shade50, title: const Row( children: [ Icon(Icons.warning, color: Colors.red), SizedBox(width: 8), Text('操作冲突', style: TextStyle(color: Colors.red)), ], ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: contentParts, ), actions: [ TextButton( onPressed: () { _feedbackService.stopAlert(); Navigator.pop(ctx); }, child: const Text('关闭'), ), ], ), ); } Future _showCrossPaichaDialog(String newZongpaiNo) async { final currentPaicha = _overview?.paichaNo ?? '--'; final shouldSwitch = await _confirmCrossPaichaSwitch( newZongpaiNo: newZongpaiNo, currentPaicha: currentPaicha, ); if (!mounted) return; if (shouldSwitch) { _switchToNewPaicha(newZongpaiNo); return; } setState(() { _crossPaichaPending = false; }); } Future _confirmCrossPaichaSwitch({ required String newZongpaiNo, required String currentPaicha, }) async { final dialogFocus = FocusNode(); var dismissed = false; var selectedIndex = 0; // 0 = "否" (default), 1 = "是" void dismissAsNo() { if (dismissed) return; dismissed = true; Navigator.of(context).pop(false); } void confirmSwitch() { if (dismissed) return; dismissed = true; Navigator.of(context).pop(true); } final dialogFuture = showDialog( context: context, barrierDismissible: false, builder: (ctx) => StatefulBuilder( builder: (ctx, setDialogState) { return KeyboardListener( focusNode: dialogFocus, onKeyEvent: (event) { if (event is! KeyDownEvent) return; if (event.logicalKey == LogicalKeyboardKey.arrowUp) { setDialogState(() => selectedIndex = 0); } else if (event.logicalKey == LogicalKeyboardKey.arrowDown) { setDialogState(() => selectedIndex = 1); } else if (event.logicalKey == LogicalKeyboardKey.enter) { selectedIndex == 0 ? dismissAsNo() : confirmSwitch(); } else if (event.logicalKey == LogicalKeyboardKey.escape) { dismissAsNo(); } }, child: PopScope( canPop: false, onPopInvokedWithResult: (didPop, _) { if (!didPop) dismissAsNo(); }, child: AlertDialog( backgroundColor: Colors.orange.shade50, title: Row( children: [ Icon(Icons.warning_amber, color: Colors.orange.shade800), const SizedBox(width: 8), Text( '跨排产号扫描', style: TextStyle(color: Colors.orange.shade900), ), ], ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( '总排号 $newZongpaiNo 不属于当前排产号($currentPaicha),' '是否切换到新的排产号?\n\n' '选择「是」将放弃当前已扫描的所有数据。', style: const TextStyle(fontSize: 14), ), const SizedBox(height: 16), _dialogOptionBtn( label: '否', selected: selectedIndex == 0, onTap: dismissAsNo, ), const SizedBox(height: 8), _dialogOptionBtn( label: '是,切换排产号', selected: selectedIndex == 1, onTap: confirmSwitch, ), ], ), ), ), ); }, ), ); WidgetsBinding.instance.addPostFrameCallback((_) { dialogFocus.requestFocus(); }); final shouldSwitch = await dialogFuture; return shouldSwitch ?? false; } Widget _dialogOptionBtn({ required String label, required bool selected, required VoidCallback onTap, }) { return SizedBox( width: double.infinity, height: 40, child: ElevatedButton( onPressed: onTap, style: ElevatedButton.styleFrom( backgroundColor: selected ? Colors.blue.shade700 : Colors.grey.shade200, foregroundColor: selected ? Colors.white : Colors.black87, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: Text( label, style: TextStyle( fontWeight: selected ? FontWeight.w800 : FontWeight.w600, ), ), ), ); } void _switchToNewPaicha(String newZongpaiNo) { _feedbackService.trigger(FeedbackEvent.paichanSwitch); setState(() { _crossPaichaPending = false; _zongpaiNos.clear(); _zongpaiNos.add(newZongpaiNo); _overview = null; _overviewNotFound = false; _overviewError = null; _clearStatusOverride(); }); _loadOverview(newZongpaiNo); } }