// ignore_for_file: invalid_use_of_protected_member part of '../../registration_page.dart'; extension _RegistrationWidgetsPart on _RegistrationPageState { String _locationLabel(CodeType? type) { if (type == CodeType.locationTransit) return '转运区域'; if (type == CodeType.locationTempStorage) return '暂存货架'; return '普通货架'; } Color _locationLabelColor(CodeType? type) { if (type == CodeType.locationTransit) return Colors.orange; if (type == CodeType.locationTempStorage) return const Color(0xFF7B1FA2); return Colors.blue; } Widget _buildModePill() { return BoxingModePill( isSingle: _mode == RegistrationMode.singleCode, label: _mode == RegistrationMode.singleCode ? '单码上架' : '多码上架', enabled: !_isSubmitting, onTap: _cycleMode, ); } Widget _buildLocationChip() { final color = _locationLabelColor(_locationType); return Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: color.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(4), ), child: Text( _locationLabel(_locationType), style: TextStyle( fontSize: 11, color: color, fontWeight: FontWeight.bold, ), ), ); } // === Paicha Header === Widget _buildPaichaHeader() { final overview = _overview; final hasData = overview?.success == true; final hasLoc = _locationCode != null; final stats = registration_calculations.overviewStats(overview); return Container( padding: const EdgeInsets.fromLTRB(12, 8, 12, 6), decoration: BoxDecoration( color: Colors.grey.shade50, border: Border(bottom: BorderSide(color: Colors.grey.shade300)), ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( hasData ? (overview!.paichaNo ?? '--') : '--', style: TextStyle( fontSize: 24, fontWeight: FontWeight.w800, color: hasData ? Colors.black87 : Colors.grey.shade400, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ if (hasLoc) Row( mainAxisSize: MainAxisSize.min, children: [ Text( _locationCode!, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: Colors.black54, ), ), const SizedBox(width: 5), _buildLocationChip(), ], ), Row( mainAxisSize: MainAxisSize.min, children: [ _buildStatTag( '共 ${stats.totalCount}', const Color(0xFFE3F2FD), const Color(0xFF1565C0), hasData, ), _buildStatTag( '上架 ${stats.shelvedCount}', const Color(0xFFE8F5E9), const Color(0xFF2E7D32), hasData, ), _buildStatTag( '转运 ${stats.transferredCount}', const Color(0xFFFFF3E0), const Color(0xFFE65100), hasData, ), _buildStatTag( '暂存 ${stats.tempStoredCount}', const Color(0xFFF3E5F5), const Color(0xFF7B1FA2), hasData, ), ], ), ], ), ), ], ), ); } Widget _buildStatTag(String text, Color bg, Color fg, bool hasData) { return Container( padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 1), margin: const EdgeInsets.only(left: 5), decoration: BoxDecoration( color: hasData ? bg : const Color(0xFFF5F5F5), borderRadius: BorderRadius.circular(10), ), child: Text( text, style: TextStyle( fontSize: 10, fontWeight: FontWeight.w700, color: hasData ? fg : Colors.grey.shade400, ), ), ); } // === Table Head === Widget _buildTableHead() { return Container( height: 28, padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: Colors.grey.shade200, border: Border(bottom: BorderSide(color: Colors.grey.shade400)), ), child: const Row( children: [ Expanded( flex: 22, child: Text( '总排号', textAlign: TextAlign.center, style: _headerStyle, ), ), Expanded( flex: 18, child: Text( '工令号', textAlign: TextAlign.center, style: _headerStyle, ), ), Expanded( flex: 12, child: Text('数量', textAlign: TextAlign.center, style: _headerStyle), ), Expanded( flex: 28, child: Text( '货位号', textAlign: TextAlign.center, style: _headerStyle, ), ), ], ), ); } // === List Body === Widget _buildListBody() { if (_overviewZongpaiNo == null) { return _buildListMessage('扫描总排号后自动显示排产号上架情况'); } if (_overviewLoading && _overview == null) { return _buildListMessage('正在加载排产号上架情况…'); } if (_overviewNotFound) { return _buildListMessage('暂无排产信息'); } if (_overviewError != null && _overview == null) { return _buildListError(_overviewError!); } final overview = _overview; if (overview == null || !overview.success) { return _buildListMessage('扫描总排号后自动显示排产号上架情况'); } final sections = registration_calculations.splitOverviewItems( overview: overview, zongpaiNos: _zongpaiNos, ); final scanned = sections.scanned; final unscanned = sections.unscanned; return Column( children: [ if (_overviewError != null) Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), color: Colors.red.shade50, child: Row( children: [ Expanded( child: Text( _overviewError!, style: const TextStyle(fontSize: 12, color: Colors.red), ), ), TextButton( onPressed: _overviewZongpaiNo == null ? null : () => _loadOverview(_overviewZongpaiNo!, force: true), child: const Text('重试'), ), ], ), ), Expanded( child: ListView.builder( itemCount: scanned.length + (sections.hasDivider ? 1 : 0) + unscanned.length, itemBuilder: (context, index) { if (index < scanned.length) { return _buildListRow(scanned[index], isScanned: true); } if (index == scanned.length && sections.hasDivider) { return _buildSectionDivider(unscanned.length); } final unscannedIdx = index - scanned.length - (sections.hasDivider ? 1 : 0); return _buildListRow(unscanned[unscannedIdx], isScanned: false); }, ), ), ], ); } Widget _buildSectionDivider(int count) { return Container( height: 24, padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey.shade200)), ), child: Row( children: [ const Expanded(child: Divider(height: 0)), Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: Text( '以下 $count 项未操作', style: TextStyle( fontSize: 10, fontWeight: FontWeight.w600, color: Colors.grey.shade500, ), ), ), const Expanded(child: Divider(height: 0)), ], ), ); } Widget _buildListRow(PaichaOverviewItem item, {required bool isScanned}) { final rowStyle = TextStyle( fontSize: 15, fontWeight: isScanned ? FontWeight.w700 : FontWeight.w500, color: Colors.black87, ); final barColor = registration_calculations.registrationBarColor( status: item.status, isScanned: isScanned, isTransitTarget: _isTransitTarget, isTempStorageTarget: _isTempStorageTarget, ); final bgColor = registration_calculations.registrationRowBgColor( status: item.status, isScanned: isScanned, isTransitTarget: _isTransitTarget, isTempStorageTarget: _isTempStorageTarget, ); return Container( constraints: const BoxConstraints(minHeight: 36), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: bgColor, border: Border( left: BorderSide(color: barColor, width: 3), bottom: BorderSide(color: Colors.grey.shade200), ), ), child: Row( children: [ Expanded( flex: 22, child: Text( item.zongpaiNo, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: rowStyle, ), ), Expanded( flex: 18, child: Text( item.workOrderNo ?? '--', textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: rowStyle, ), ), Expanded( flex: 12, child: Text( item.quantity.toString(), textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: rowStyle, ), ), Expanded( flex: 28, child: Text( item.locationCode ?? '\u2014', textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: rowStyle, ), ), if (isScanned && _mode == RegistrationMode.multiCode) ...[ const SizedBox(width: 6), SizedBox( width: 28, height: 28, child: IconButton( icon: Icon(Icons.delete_outline, size: 16), color: Colors.red, onPressed: () => _removeZongpai(item.zongpaiNo), padding: EdgeInsets.zero, constraints: const BoxConstraints(minWidth: 28, minHeight: 28), ), ), ], ], ), ); } Widget _buildListMessage(String text) { return Center( child: Text( text, textAlign: TextAlign.center, style: TextStyle(fontSize: 13, color: Colors.grey.shade600), ), ); } Widget _buildListError(String text) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( text, textAlign: TextAlign.center, style: const TextStyle(fontSize: 13, color: Colors.red), ), const SizedBox(height: 6), TextButton( onPressed: _overviewZongpaiNo == null ? null : () => _loadOverview(_overviewZongpaiNo!, force: true), child: const Text('重试'), ), ], ), ); } // === Bottom Bar === Widget _buildBottomBar(ColorScheme colorScheme) { return Container( decoration: BoxDecoration( color: Colors.white, border: Border(top: BorderSide(color: Colors.grey.shade300)), ), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: SizedBox( width: double.infinity, height: 34, child: ElevatedButton( onPressed: _canSubmit ? _submit : null, style: ElevatedButton.styleFrom( backgroundColor: registrationSubmitColor( canSubmit: _canSubmit, isTransitTarget: _isTransitTarget, primaryColor: colorScheme.primary, ), foregroundColor: _canSubmit ? Colors.white : Colors.grey.shade600, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6), ), ), child: _isSubmitting ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : Text( registrationSubmitLabel( isTransitTarget: _isTransitTarget, isMultiCode: _mode == RegistrationMode.multiCode, zongpaiCount: _zongpaiNos.length, ), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w700, ), ), ), ), ); } } const _headerStyle = TextStyle(fontSize: 10, fontWeight: FontWeight.w700);