117 lines
3.6 KiB
Dart
117 lines
3.6 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:pad_scanner/services/app_config_service.dart';
|
|
import 'package:pad_scanner/services/scanner_service.dart';
|
|
import 'package:pad_scanner/services/code_parser.dart';
|
|
import 'package:pad_scanner/services/api_service.dart';
|
|
import 'package:pad_scanner/services/feedback_service.dart';
|
|
import 'package:pad_scanner/services/registration_linking.dart';
|
|
import 'package:vibration/vibration.dart';
|
|
import 'package:pad_scanner/pages/boxing_page.dart';
|
|
import 'package:pad_scanner/widgets/status_bar.dart';
|
|
import 'package:pad_scanner/pages/boxing/widgets/boxing_shared_widgets.dart';
|
|
import 'package:pad_scanner/pages/registration/registration_calculations.dart'
|
|
as registration_calculations;
|
|
|
|
part 'registration/parts/registration_scan_part.dart';
|
|
part 'registration/parts/registration_status_part.dart';
|
|
part 'registration/parts/registration_overview_part.dart';
|
|
part 'registration/parts/registration_submit_part.dart';
|
|
part 'registration/parts/registration_mode_part.dart';
|
|
part 'registration/dialogs/registration_dialogs_part.dart';
|
|
part 'registration/widgets/registration_widgets_part.dart';
|
|
|
|
enum RegistrationMode {
|
|
singleCode, // 单码上架
|
|
multiCode, // 多码上架
|
|
}
|
|
|
|
class RegistrationPage extends StatefulWidget {
|
|
const RegistrationPage({super.key});
|
|
|
|
@override
|
|
State<RegistrationPage> createState() => _RegistrationPageState();
|
|
}
|
|
|
|
class _RegistrationPageState extends State<RegistrationPage> {
|
|
final _scannerService = ScannerService();
|
|
final _apiService = ApiService();
|
|
final _feedbackService = FeedbackService();
|
|
final _focusNode = FocusNode();
|
|
|
|
StreamSubscription<ScanResult>? _scanSubscription;
|
|
final _zongpaiNos = <String>[];
|
|
String? _locationCode;
|
|
CodeType? _locationType;
|
|
RegistrationMode _mode = RegistrationMode.singleCode;
|
|
bool _isSubmitting = false;
|
|
|
|
StatusDotColor _statusDot = StatusDotColor.blue;
|
|
String _statusText = '等待扫描总排号或货位号…';
|
|
String? _statusOverrideText;
|
|
StatusDotColor? _statusOverrideDot;
|
|
|
|
bool _overviewLoading = false;
|
|
bool _overviewNotFound = false;
|
|
String? _overviewError;
|
|
String? _overviewZongpaiNo;
|
|
PaichaOverviewResult? _overview;
|
|
int _overviewRequestId = 0;
|
|
|
|
/// Whether a cross-paicha warning dialog is currently showing.
|
|
bool _crossPaichaPending = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_startScanListening();
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
_focusNode.requestFocus();
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_scanSubscription?.cancel();
|
|
_focusNode.dispose();
|
|
_feedbackService.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final colorScheme = Theme.of(context).colorScheme;
|
|
_updateBaseStatus();
|
|
final effectiveDot = _statusOverrideDot ?? _statusDot;
|
|
final effectiveText = _statusOverrideText ?? _statusText;
|
|
|
|
return KeyboardListener(
|
|
focusNode: _focusNode,
|
|
onKeyEvent: _onKeyEvent,
|
|
child: Scaffold(
|
|
appBar: AppBar(
|
|
title: Row(
|
|
children: [
|
|
const Text('上架登记'),
|
|
const SizedBox(width: 12),
|
|
Expanded(child: _buildModePill()),
|
|
],
|
|
),
|
|
titleSpacing: 12,
|
|
),
|
|
body: Column(
|
|
children: [
|
|
_buildPaichaHeader(),
|
|
if (_overview?.success == true) _buildTableHead(),
|
|
Expanded(child: _buildListBody()),
|
|
_buildBottomBar(colorScheme),
|
|
StatusBar(dotColor: effectiveDot, text: effectiveText),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|