Recognize B-prefix location codes as temp storage shelves. Add purple color scheme, conflict detection for temp_stored status, and updated submit/dialog logic for temp storage target handling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
130 lines
3.6 KiB
Dart
130 lines
3.6 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:
|
|
case CodeType.locationTempStorage:
|
|
_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);
|
|
});
|
|
}
|
|
}
|