From f60745607fdd8d71e2844d77a841df080ced6b9d Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Mon, 18 May 2026 17:00:40 +0800 Subject: [PATCH] refine boxing UI: restructure info bar, scan bar, and mode switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Info bar: left-right layout with progress bar below, detail button on right - Scan bar: remove '已识别' badge, show 工令号/总件数/已装X with larger font - Mode switch: move to title right side, adopt rectangular style with 18px bold font Co-Authored-By: Claude Opus 4.6 --- docs/single-code-boxing-ui-v2.html | 176 +++++++++++--------- lib/pages/boxing_page.dart | 258 +++++++++++++---------------- 2 files changed, 215 insertions(+), 219 deletions(-) diff --git a/docs/single-code-boxing-ui-v2.html b/docs/single-code-boxing-ui-v2.html index 69ba195..0e888a2 100644 --- a/docs/single-code-boxing-ui-v2.html +++ b/docs/single-code-boxing-ui-v2.html @@ -189,7 +189,7 @@ body { flex-shrink: 0; } .scan-code { - font-size: 13px; + font-size: 20px; font-weight: 700; color: var(--text); flex: 1; @@ -197,6 +197,14 @@ body { text-overflow: ellipsis; white-space: nowrap; } +.scan-zongpai-extra { + font-size: 11px; + color: var(--text-2); + font-weight: 500; + flex-shrink: 0; + white-space: nowrap; + margin-right: 4px; +} .scan-badge { font-size: 10px; font-weight: 700; @@ -216,7 +224,7 @@ body { display: flex; flex-direction: column; position: relative; - padding: 8px 86px 8px 12px; + padding: 8px 12px 8px 12px; border-bottom: 1px solid var(--border); flex-shrink: 0; background: #fafafa; @@ -248,13 +256,19 @@ body { white-space: nowrap; } +/* 进度条+详情同行 */ +.progress-with-detail { + display: flex; + align-items: center; + gap: 8px; +} /* 进度条 */ .progress-wrap { + flex: 1; height: 3px; background: #e0e0e0; border-radius: 2px; overflow: hidden; - margin: 2px 0; } .progress-fill { height: 100%; @@ -264,29 +278,13 @@ body { } .progress-fill.full { background: var(--green); } -.info-row2 { - display: flex; - align-items: center; - gap: 4px; -} -.info-meta-text { - font-size: 11px; - color: var(--text-3); - flex: 1; -} -.info-meta-text .hl { color: var(--amber); font-weight: 700; } -.info-meta-text .packed { color: var(--blue); font-weight: 600; } - .detail-link { - position: absolute; - right: 12px; - top: 50%; - transform: translateY(-50%); display: inline-flex; align-items: center; - gap: 4px; - height: 34px; - font-size: 12px; + justify-content: center; + height: 28px; + min-width: 48px; + font-size: 11px; font-weight: 700; color: var(--blue); background: var(--blue-lt); @@ -309,10 +307,21 @@ body { cursor: default; } +.info-row2 { + display: flex; + align-items: center; + gap: 4px; +} +.info-meta-text { + font-size: 11px; + color: var(--text-3); + flex: 1; +} +.info-meta-text .hl { color: var(--amber); font-weight: 700; } +.info-meta-text .packed { color: var(--blue); font-weight: 600; } + /* 空状态的 info-bar */ .info-bar.empty .info-paichan, -.info-bar.empty .info-wo, -.info-bar.empty .info-erp, .info-bar.empty .info-meta-text { color: #ccc; } /* ── 已分配列表区 (可滚动) ── */ @@ -661,15 +670,15 @@ body {
排产号 — - 工单 — - — 件
-
-
+
+
+
+
+
已有 — 箱 · 最大箱号 — -
@@ -718,6 +727,7 @@ body {
ZP202605180001 + WO-2026-0882 / 200件 已识别
@@ -725,15 +735,15 @@ body {
PC-2605-A101 - WO-2026-0882 - 200 件
-
-
+
+
+
+
+
已有 1 箱 · 最大箱号 2 · 已装 50/200 -
@@ -781,21 +791,22 @@ body {
ZP202605180001 + WO-2026-0882 / 200件 已识别
PC-2605-A101 - WO-2026-0882 - 200 件
-
-
+
+
+
+
+
已有 3 箱 · 最大箱号 7 · 已装 150/200 -
@@ -866,21 +877,22 @@ body {
ZP202605180001 + WO-2026-0882 / 200件 已识别
PC-2605-A101 - WO-2026-0882 - 200 件
-
-
+
+
+
+
+
已有 3 箱 · 最大箱号 7 · 已装 150/200 -
@@ -951,21 +963,22 @@ body {
ZP202605180001 + WO-2026-0882 / 200件 已识别
PC-2605-A101 - WO-2026-0882 - 200 件
-
-
+
+
+
+
+
已有 3 箱 · 最大箱号 7 -
@@ -1041,21 +1054,22 @@ body {
ZP202605180001 + WO-2026-0882 / 200件 已识别
PC-2605-A101 - WO-2026-0882 - 200 件
-
-
+
+
+
+
+
已有 1 箱 · 最大箱号 2 -
@@ -1109,21 +1123,22 @@ body {
ZP202605180001 + WO-2026-0882 / 200件 已识别
PC-2605-A101 - WO-2026-0882 - 200 件
-
-
+
+
+
+
+
已有 2 箱 · 最大箱号 5 -
@@ -1175,21 +1190,22 @@ body {
ZP202605180001 + WO-2026-0882 / 200件 已识别
PC-2605-A101 - WO-2026-0882 - 200 件
-
-
+
+
+
+
+
已有 1 箱 · 最大箱号 2 · 剩余可装 150 -
@@ -1241,21 +1257,22 @@ body {
ZP202605180002 + WO-2026-0901 / 100件 已识别
PC-2605-B202 - WO-2026-0901 - 100 件
-
-
+
+
+
+
+
已有 3 箱 · 最大箱号 3 · 100/100 已装完 -
@@ -1347,21 +1364,22 @@ body {
ZP202605180001 + WO-2026-0882 / 200件 已识别
PC-2605-A101 - WO-2026-0882 - 200 件
-
-
+
+
+
+
+
已有 3 箱 · 最大箱号 7 · 已装 150/200 -
@@ -1456,10 +1474,10 @@ body { │ "装箱编号" [⇄ 单码装箱 P2] │ AppBar ├──────────────────────────────────────────┤ │ [通知条] 可叠加显示,每条 ~30px │ 可选 -├──────────────────────────────────────────┤ 38px -│ ✓ ZP202605180001 已识别 │ 扫码条 -├──────────────────────────────────────────┤ ~52px -│ PC-2605-A101 WO-2026-0882 200件 [详情]│ +├──────────────────────────────────────────┤ ~50px +│ ✓ ZP202605180001 WO-0882 / 200件 已识别 │ 扫码条 +├──────────────────────────────────────────┤ ~45px +│ PC-2605-A101 [详情] │ │ ▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 进度条 │ info-bar │ 已有 2箱 · 最大箱号 5 · 已装50/200 │ ├──────────────────────────────────────────┤ diff --git a/lib/pages/boxing_page.dart b/lib/pages/boxing_page.dart index 4369e3b..616040c 100644 --- a/lib/pages/boxing_page.dart +++ b/lib/pages/boxing_page.dart @@ -1305,10 +1305,15 @@ class _BoxingPageState extends State with WidgetsBindingObserver { onKeyEvent: _onKeyEvent, child: Scaffold( appBar: AppBar( - title: const Text('装箱编号'), + title: Row( + children: [ + const Text('装箱编号'), + const SizedBox(width: 8), + _buildModePill(), + ], + ), toolbarHeight: 44, titleSpacing: 12, - actions: [_buildModePill(), const SizedBox(width: 8)], ), body: Column( children: [ @@ -1446,27 +1451,10 @@ class _BoxingPageState extends State with WidgetsBindingObserver { ); } - Widget _buildSingleCodeBody(ColorScheme colorScheme) { - final isWaiting = _phase == _Phase.waiting && _zongpaiNo == null; - final isFinished = - _phase == _Phase.scanned && - _zongpaiNo != null && - _remainingQuantity <= 0; - - return Column( - children: [ - _buildSingleScanBar(isWaiting), - _buildSingleInfoBar(isWaiting, colorScheme), - _buildSingleAssignedList(isWaiting, isFinished), - _buildSingleBottomArea(isWaiting || isFinished), - ], - ); - } - Widget _buildSingleScanBar(bool isWaiting) { if (isWaiting) { return Container( - height: 38, + height: 50, padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: Colors.grey.shade100, @@ -1486,7 +1474,7 @@ class _BoxingPageState extends State with WidgetsBindingObserver { } return Container( - height: 38, + height: 50, padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( color: Colors.green.shade50, @@ -1499,23 +1487,17 @@ class _BoxingPageState extends State with WidgetsBindingObserver { Expanded( child: Text( _zongpaiNo ?? '', - style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w700), + style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w700), overflow: TextOverflow.ellipsis, ), ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 1), - decoration: BoxDecoration( - color: Colors.green.shade100, - borderRadius: BorderRadius.circular(8), - ), - child: Text( - '已识别', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w700, - color: Colors.green.shade700, - ), + const SizedBox(width: 8), + Text( + '${_workOrderNo ?? "--"} / ${_erpQuantity ?? 0}件 / 已装$_packedQuantity', + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500, + color: Colors.black54, ), ), ], @@ -1523,6 +1505,23 @@ class _BoxingPageState extends State with WidgetsBindingObserver { ); } + Widget _buildSingleCodeBody(ColorScheme colorScheme) { + final isWaiting = _phase == _Phase.waiting && _zongpaiNo == null; + final isFinished = + _phase == _Phase.scanned && + _zongpaiNo != null && + _remainingQuantity <= 0; + + return Column( + children: [ + _buildSingleScanBar(isWaiting), + _buildSingleInfoBar(isWaiting, colorScheme), + _buildSingleAssignedList(isWaiting, isFinished), + _buildSingleBottomArea(isWaiting || isFinished), + ], + ); + } + Widget _buildSingleInfoBar(bool isWaiting, ColorScheme colorScheme) { final total = _erpQuantity ?? 0; final packed = isWaiting ? 0 : _packedQuantity; @@ -1531,90 +1530,68 @@ class _BoxingPageState extends State with WidgetsBindingObserver { final detailEnabled = !isWaiting && _existingBoxes.isNotEmpty; return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.grey.shade50, border: Border(bottom: BorderSide(color: Colors.grey.shade300)), ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - Expanded( - child: Text( + child: IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Text( isWaiting ? '排产号 --' : (_paichanNo ?? '--'), style: TextStyle( fontSize: 14, fontWeight: FontWeight.w700, - color: isWaiting - ? Colors.grey.shade400 - : Colors.black87, + color: isWaiting ? Colors.grey.shade400 : Colors.black87, ), overflow: TextOverflow.ellipsis, ), - ), - const SizedBox(width: 8), - Text( - isWaiting ? '工单 --' : (_workOrderNo ?? '--'), - style: TextStyle( - fontSize: 12, - color: isWaiting - ? Colors.grey.shade400 - : Colors.black54, + const SizedBox(width: 10), + Expanded( + child: Text( + isWaiting + ? '已有 -- 箱 · 最大箱号 --' + : '已有 ${_existingBoxes.length} 箱 · 最大箱号 $_maxBoxNo', + style: TextStyle( + fontSize: 10, + color: isWaiting + ? Colors.grey.shade400 + : Colors.grey.shade600, + ), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.right, + ), + ), + ], + ), + const SizedBox(height: 4), + ClipRRect( + borderRadius: BorderRadius.circular(2), + child: LinearProgressIndicator( + value: progress, + minHeight: 3, + backgroundColor: Colors.grey.shade300, + valueColor: AlwaysStoppedAnimation( + finished ? Colors.green.shade700 : colorScheme.primary, ), ), - const SizedBox(width: 8), - Text( - isWaiting ? '-- 件' : '$total 件', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - color: isWaiting - ? Colors.grey.shade400 - : Colors.black87, - ), - ), - ], - ), - const SizedBox(height: 5), - ClipRRect( - borderRadius: BorderRadius.circular(2), - child: LinearProgressIndicator( - value: progress, - minHeight: 3, - backgroundColor: Colors.grey.shade300, - valueColor: AlwaysStoppedAnimation( - finished ? Colors.green.shade700 : colorScheme.primary, - ), ), - ), - const SizedBox(height: 5), - Align( - alignment: Alignment.centerLeft, - child: Text( - isWaiting - ? '已有 -- 箱 · 最大箱号 --' - : '已有 ${_existingBoxes.length} 箱 · 最大箱号 $_maxBoxNo · 已装 $packed/$total', - style: TextStyle( - fontSize: 11, - color: isWaiting - ? Colors.grey.shade400 - : Colors.grey.shade600, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], + ], + ), ), - ), - const SizedBox(width: 10), - _buildDetailButton(detailEnabled, colorScheme), - ], + const SizedBox(width: 10), + _buildDetailButton(detailEnabled, colorScheme), + ], + ), ), ); } @@ -2064,44 +2041,45 @@ class _BoxingPageState extends State with WidgetsBindingObserver { final isSingle = _mode == BoxingMode.singleCode; final bgColor = isSingle ? Colors.blue.shade700 : Colors.orange.shade700; - return GestureDetector( - onTap: _isAutoProcessing ? null : _cycleMode, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 9, vertical: 3), - decoration: BoxDecoration( - color: bgColor, - borderRadius: BorderRadius.circular(12), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.swap_horiz, color: Colors.white, size: 14), - const SizedBox(width: 4), - Text( - _modeLabel, - style: const TextStyle( - color: Colors.white, - fontSize: 11, - fontWeight: FontWeight.w700, - ), - ), - const SizedBox(width: 4), - Container( - padding: const EdgeInsets.symmetric(horizontal: 4), - decoration: BoxDecoration( - color: Colors.white.withValues(alpha: 0.22), - borderRadius: BorderRadius.circular(4), - ), - child: const Text( - 'P2', - style: TextStyle( - color: Colors.white, - fontSize: 10, - fontWeight: FontWeight.w600, + return Material( + borderRadius: BorderRadius.circular(8), + color: bgColor, + child: InkWell( + borderRadius: BorderRadius.circular(8), + onTap: _isAutoProcessing ? null : _cycleMode, + child: Container( + height: 36, + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.swap_horiz, color: Colors.white, size: 18), + const SizedBox(width: 6), + Flexible( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + _modeLabel, + maxLines: 1, + style: const TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.w800, + ), + ), ), ), - ), - ], + const SizedBox(width: 8), + Text( + 'P2', + style: TextStyle( + color: Colors.white.withValues(alpha: 0.88), + fontSize: 12, + fontWeight: FontWeight.w700, + ), + ), + ], + ), ), ), );