In multi-code shelving mode, if the user has scanned zongpai numbers but hasn't scanned any shelf yet, scanning the first shelf should not trigger the "switch shelf" warning dialog since there is no existing shelf to switch from. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
129 lines
3.5 KiB
Dart
129 lines
3.5 KiB
Dart
// ignore_for_file: invalid_use_of_protected_member
|
|
|
|
part of '../../registration_page.dart';
|
|
|
|
extension _RegistrationScanPart on _RegistrationPageState {
|
|
void _startScanListening() {
|
|
_scanSubscription ??= _scannerService.scanResults.listen(_onScan);
|
|
}
|
|
|
|
Future<void> _stopScanListening() async {
|
|
final subscription = _scanSubscription;
|
|
_scanSubscription = null;
|
|
await subscription?.cancel();
|
|
}
|
|
|
|
void _restartScanListening() {
|
|
_scanSubscription?.cancel();
|
|
_scanSubscription = null;
|
|
_startScanListening();
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (mounted) {
|
|
_focusNode.requestFocus();
|
|
}
|
|
});
|
|
}
|
|
|
|
void _onKeyEvent(KeyEvent event) {
|
|
if (event is! KeyDownEvent) return;
|
|
if (_isLockToggleKey(event)) {
|
|
_cycleMode();
|
|
return;
|
|
}
|
|
if (event.logicalKey == LogicalKeyboardKey.enter) {
|
|
_submit();
|
|
}
|
|
}
|
|
|
|
bool _isLockToggleKey(KeyEvent event) {
|
|
final key = event.logicalKey;
|
|
return key == LogicalKeyboardKey.select ||
|
|
key == LogicalKeyboardKey.gameButtonRight1;
|
|
}
|
|
|
|
void _onScan(ScanResult result) {
|
|
final parsed = CodeParser.parse(result.barcode);
|
|
switch (parsed.type) {
|
|
case CodeType.zongpaiNo:
|
|
_handleZongpaiScan(parsed.value);
|
|
case CodeType.locationNormal:
|
|
case CodeType.locationTransit:
|
|
_handleLocationScan(parsed.value, parsed.type);
|
|
case CodeType.invalid:
|
|
_feedbackService.trigger(FeedbackEvent.scanInvalid);
|
|
_showStatusOverride(
|
|
'无效码:${result.barcode}',
|
|
StatusDotColor.red,
|
|
const Duration(seconds: 2),
|
|
);
|
|
}
|
|
}
|
|
|
|
void _handleLocationScan(String locationCode, CodeType locationType) {
|
|
// In singleCode mode or no existing data or no previous shelf, switch directly
|
|
if (_mode == RegistrationMode.singleCode ||
|
|
_zongpaiNos.isEmpty ||
|
|
_locationCode == null) {
|
|
_feedbackService.trigger(FeedbackEvent.scanValid);
|
|
setState(() {
|
|
_locationCode = locationCode;
|
|
_locationType = locationType;
|
|
_clearStatusOverride();
|
|
});
|
|
return;
|
|
}
|
|
|
|
// In multiCode mode with existing data, confirm before switching
|
|
_showLocationSwitchDialog(locationCode, locationType);
|
|
}
|
|
|
|
void _handleZongpaiScan(String zongpaiNo) {
|
|
// If cross-paicha dialog is showing, just vibrate and discard
|
|
if (_crossPaichaPending) {
|
|
_triggerDoubleVibration();
|
|
return;
|
|
}
|
|
|
|
// In multiCode mode with existing data, check for cross-paicha scan
|
|
if (_mode == RegistrationMode.multiCode &&
|
|
_zongpaiNos.isNotEmpty &&
|
|
_overview?.success == true &&
|
|
!_overview!.items.any((item) => item.zongpaiNo == zongpaiNo)) {
|
|
_crossPaichaPending = true;
|
|
_triggerDoubleVibration();
|
|
_showCrossPaichaDialog(zongpaiNo);
|
|
return;
|
|
}
|
|
|
|
final shouldRefresh = _overviewZongpaiNo != zongpaiNo;
|
|
_feedbackService.trigger(FeedbackEvent.scanValid);
|
|
setState(() {
|
|
if (_mode == RegistrationMode.multiCode) {
|
|
if (!_zongpaiNos.contains(zongpaiNo)) {
|
|
_zongpaiNos.add(zongpaiNo);
|
|
}
|
|
} else {
|
|
if (_zongpaiNos.isEmpty) {
|
|
_zongpaiNos.add(zongpaiNo);
|
|
} else {
|
|
_zongpaiNos[0] = zongpaiNo;
|
|
}
|
|
}
|
|
_clearStatusOverride();
|
|
});
|
|
if (shouldRefresh) {
|
|
_loadOverview(zongpaiNo);
|
|
}
|
|
}
|
|
|
|
void _triggerDoubleVibration() {
|
|
Vibration.vibrate(pattern: [0, 200, 100, 200]);
|
|
}
|
|
|
|
void _removeZongpai(String zongpaiNo) {
|
|
setState(() {
|
|
_zongpaiNos.remove(zongpaiNo);
|
|
});
|
|
}
|
|
}
|