improve single-code boxing UX: preserve state, fix work order display, add double-vibrate alert

- Keep UI state after boxing completion for operator review instead of auto-reset
- Show real work order number instead of hardcoded "本次扫码" in assigned list
- Add double-vibration feedback when re-scanning already completed zongpai
- Change completed status banner and dot from green to red for clearer warning

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-05-19 17:05:26 +08:00
parent 7a95f49acc
commit a6ee6a718b
2 changed files with 29 additions and 10 deletions

View File

@@ -344,7 +344,19 @@ class _BoxingPageState extends State<BoxingPage> with WidgetsBindingObserver {
return false;
}
_feedbackService.trigger(FeedbackEvent.scanValid);
// 判断该总牌号是否已全部装箱完毕
final packedQuantity = result.currentZongpaiBoxes.fold<int>(
0,
(sum, item) => sum + item.quantity,
);
final totalQuantity = result.quantity ?? 0;
final alreadyCompleted = totalQuantity > 0 && packedQuantity >= totalQuantity;
_feedbackService.trigger(
alreadyCompleted
? FeedbackEvent.alreadyCompleted
: FeedbackEvent.scanValid,
);
setState(() {
_zongpaiNo = zongpai;
@@ -686,9 +698,6 @@ class _BoxingPageState extends State<BoxingPage> with WidgetsBindingObserver {
StatusDotColor.green,
const Duration(milliseconds: 1500),
);
Future.delayed(const Duration(milliseconds: 1500), () {
if (mounted) setState(() => _resetState());
});
} else {
setState(() {
_phase = _Phase.scanned;
@@ -1285,7 +1294,7 @@ class _BoxingPageState extends State<BoxingPage> with WidgetsBindingObserver {
case _Phase.scanned:
_statusDot = StatusDotColor.blue;
if (_remainingQuantity <= 0) {
_statusDot = StatusDotColor.green;
_statusDot = StatusDotColor.red;
_statusText = '该总排号已全部装箱完毕';
return;
}
@@ -1423,11 +1432,11 @@ class _BoxingPageState extends State<BoxingPage> with WidgetsBindingObserver {
_remainingQuantity <= 0) {
banners.add(
_noticeBanner(
icon: Icon(Icons.check, size: 14, color: Colors.green.shade800),
icon: Icon(Icons.warning, size: 14, color: Colors.red.shade800),
text: '${_zongpaiNo!} 已全部装箱完毕,无需操作',
background: Colors.green.shade50,
foreground: Colors.green.shade800,
border: Colors.green.shade100,
background: Colors.red.shade50,
foreground: Colors.red.shade800,
border: Colors.red.shade100,
),
);
}
@@ -1762,7 +1771,7 @@ class _BoxingPageState extends State<BoxingPage> with WidgetsBindingObserver {
overflow: TextOverflow.ellipsis,
),
Text(
'本次扫码',
_workOrderNo ?? '--',
style: TextStyle(
fontSize: 10,
color: Colors.grey.shade500,

View File

@@ -10,6 +10,7 @@ enum FeedbackEvent {
duplicateError, // Duplicate (shelf) → alert loop + continuous vibrate
networkError, // Network error → failure sound + short vibrate
duplicateBoxNo, // Duplicate box no → failure sound + short vibrate
alreadyCompleted, // Zongpai already boxed → beep + double vibrate
modeSwitch, // Mode toggle → beep only
paichanSwitch, // Paichan changed → beep + short vibrate
}
@@ -55,6 +56,10 @@ class FeedbackService {
_soundService.playFailure();
_vibrateShort();
case FeedbackEvent.alreadyCompleted:
_soundService.playBeep();
_vibrateDouble();
case FeedbackEvent.modeSwitch:
_soundService.playBeep();
@@ -82,6 +87,11 @@ class FeedbackService {
Vibration.vibrate(pattern: [0, 300, 100, 300, 100, 300]);
}
/// Two short bursts to signal an already-completed item.
void _vibrateDouble() {
Vibration.vibrate(pattern: [0, 200, 100, 200]);
}
Future<void> dispose() async {
await _soundService.dispose();
}