Files
pad_scanner/lib/pages/registration_page.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),
],
),
),
);
}
}