# 单码装箱页面 UI 重构 PRD **文档版本**:v2.0 **更新日期**:2026-05-18 **涉及页面**:`lib/pages/boxing_page.dart`(BoxingMode.singleCode) **参考设计**:多码凑箱 UI v2(`multi-code-boxing-ui-v2.html`) **产出物**:`single-code-boxing-ui-v2.html` --- ## 一、背景与目标 原单码装箱页面各区块自然堆叠,当已分配记录增多或通知条出现时,下方输入区会被挤出屏幕可视范围,操作体验差。同时,原版与多码凑箱在视觉语言上存在差异,两种模式切换后用户需要重新适应布局。 **重构目标:** 1. 与多码凑箱采用统一的设计语言,降低双模式切换的认知成本 2. 采用固定顶部 + 可滚动中间 + 固定底栏结构,无论已分配记录多少,输入区始终可见 3. 在不损失信息量的前提下,压缩各区块高度,让屏幕展示更多有效内容 4. 去掉返回按钮,简化底栏操作区 --- ## 二、整体布局结构 ### v1(原版)布局 ``` AppBar(~52px) 扫码卡片(~52px) 信息区 - 排产号+工单+件数(~30px) 信息区 - 已有箱数+最大箱号+详情(~28px) 分隔线 已分配列表(自然高度,不可滚动) 输入区 - 箱号+数量+确认(~48px) 操作行 - 返回按钮(~48px) 状态栏(~38px) ``` > 问题:各区全部占据固定高度,列表一旦有 3 条以上记录,输入区就会被推出屏幕,需要手动滚动才能操作。 ### v2(重构后)布局 ``` AppBar(44px) ← 固定顶部 [通知条 × N](每条 ~30px) ← 可选,固定 扫码条(38px) ← 固定 排产信息栏(~52px) ← 固定 ━━━━━━━━━━━━━━━━━━━━━━━━━ 已分配列表(弹性高度) ← 可滚动区域 ━━━━━━━━━━━━━━━━━━━━━━━━━ 输入行(~50px) ← 固定底栏 状态栏(28px) ← 固定底栏 ``` 输入行与状态栏固定于底部,任何情况下都不会因列表增长而被遮挡。 --- ## 三、各区块改动详情 ### 3.1 AppBar | 项目 | v1 | v2 | |---|---|---| | 高度 | ~52px | **44px** | | 标题 | `装箱编号`,大号字体 | `装箱编号`,15px/700 | | 模式标识 | 独占一行的大模式按钮区 | 右侧蓝色 Pill `⇄ 单码装箱 P2`,与标题同行 | | 模式颜色 | 蓝色 | **蓝色**(单码),橙色(多码),与多码对称 | Pill 点击或按 P2 物理键切换模式,行为不变。 --- ### 3.2 通知条(Notice Banner) 替代原版内嵌式 `banner` 组件,统一为横条形通知,可多条叠加显示。 | 颜色 | 触发场景 | |---|---| | 🟠 橙色 | 正在同步转运数据 | | 🟡 琥珀色 | 箱号重复警告 / 忽略无效码 | | 🔵 蓝色 | 排产号切换提示 | | 🟢 绿色 | 全部装箱完毕提示 | | 🔴 红色 | 数量超限 / 提交失败 / 严重错误 | 每条高度约 **30px**(含 6px 上下 padding),字号 12px,图标 + 文字,`border-bottom: 1px` 与下方区域隔开。 --- ### 3.3 扫码条 | 项目 | v1 | v2 | |---|---|---| | 高度 | ~52px 卡片 | **38px** 横条 | | 等待态 | 灰色圆角卡片,居中文字 | 灰底横条,📷 图标 + 文字 | | 已识别态 | 绿色边框卡片 + 大号总排号 | 绿底横条,✓ 绿圆 + 总排号 + `已识别` 徽章 | --- ### 3.4 排产信息栏(info-bar) 原版将排产号/工单/件数与已有箱数分为两个分散区块,共约 80px。v2 合并为一个紧凑的 header-bar,高度约 **52px**。左侧包含三层信息,右侧固定放置醒目的详情按钮: ``` 左侧第一层:[排产号] [工单号] [ERP总件数] 右侧:[📋 详情] 左侧第二层:[进度条 ████████░░░░░░░░] ← 新增 左侧第三层:[已有X箱 · 最大箱号Y · 已装A/B] ``` **新增:装箱进度条** - 高度 3px,不单独占行,嵌在第一层与第三层之间 - 进度 = 已装件数 / ERP 总件数 - 未完成时为蓝色(`#1565c0`),全部装完后变绿色(`#2e7d32`) **详情入口** - 放在排产信息栏最右侧,与三层信息垂直居中 - 使用图标 + 文案的描边按钮样式,正常态为蓝色浅底,空状态置灰不可点击 **空状态**(未扫码)时,所有字段显示为灰色占位符 `—`,详情按钮置灰不可点击。 --- ### 3.5 已分配列表 原版已分配记录直接堆叠在页面中间,无法滚动。v2 改为**弹性高度可滚动区域**,与多码凑箱的「已装入本箱」列表结构完全一致。 **列表头(sticky,滚动时吸顶):** ``` 已分配(此总排号) 2 条 ``` **每行结构(高度 40px):** ``` [序号] [彩色竖条] [箱号 / 来源标注] [件数] [✏️] [🗑] ``` | 元素 | 说明 | |---|---| | 序号 | 10px 灰色,右对齐 | | 彩色竖条 | 宽 3px,高 22px;绿=正常,琥珀=编辑中,红=待删除 | | 箱号 | 13px/700,如「3 号箱」 | | 来源标注 | 10px 灰色,如「本次扫码」 | | 件数 | 13px/600,右对齐 | | 操作按钮 | ✏️ 编辑 / 🗑 删除,各 28×28px | **空状态**文案:`扫码后显示已分配箱号记录` / `本次扫码尚未分配箱号` **全部装箱完毕**时,顶部显示绿色通知 `已全部装箱完毕,无需操作`,进度条变为绿色满格,输入区禁用;已分配列表继续显示具体箱号和件数明细,避免用户只能看到完成提示却无法核对装箱结果。 #### 行内编辑态 点击 ✏️ 后该行变为编辑态(琥珀色背景 `#fff8e1`),件数文字变为输入框,操作按钮变为 ✓ 保存 / ✕ 取消。其他行保持正常可交互。 #### 删除确认态 点击 🗑 后该行背景变红(`#ffebee`),行下方展开一条 28px 确认条: ``` 确认删除 X 号箱记录? [删除] [取消] ``` 不弹出 Dialog,行内展开,减少视觉干扰。 --- ### 3.6 固定底栏(输入区) 原版输入区含三个独立行:箱号+数量+确认(~48px)、返回按钮(~48px)。 **v2 改动:** - 箱号、数量、确认按钮**合并为单行**(高度 ~50px) - **移除返回按钮** - 正在提交时:两个输入框禁用,确认按钮替换为 loading 转圈 **输入行布局:** ``` [箱号] [ 8 ] [数量] [ 50 ] [确认] ``` | 元素 | 规格 | |---|---| | 标签 | 11px/700,紧贴输入框左侧 | | 箱号输入 | 宽 52px,高 34px,居中,18px/800 | | 数量输入 | 宽 70px,高 34px,居中,16px/800 | | 确认按钮 | 高 34px,蓝底白字,14px/700 | **输入状态对应边框色:** | 状态 | 箱号输入框边框 | 数量输入框边框 | 确认按钮 | |---|---|---|---| | 正常可提交 | 蓝色 | 蓝色 | 可点击 | | 箱号重复 | **琥珀色** | 正常 | 禁用 | | 数量超限 | 正常 | **红色** | 禁用 | | 提交中 | 禁用灰 | 禁用灰 | loading 转圈 | | 等待扫码 | 禁用灰 | 禁用灰 | 禁用 | **边界规则:** 当提交后刚好装完(剩余数量变为 0)时,输入框中残留的上一次提交数量不应触发“数量超限”;此时按“全部装箱完毕”状态处理,确认按钮禁用。 --- ### 3.7 状态栏 | 项目 | v1 | v2 | |---|---|---| | 高度 | ~38px | **28px** | | 内容 | 状态圆点 + 文字 | 同,字号压缩至 11px | | 背景 | `#EEEEEE` | `#f5f5f5` | **圆点颜色语义(与多码统一):** | 颜色 | 状态 | |---|---| | 🔵 蓝 | 等待/空闲/数量已填入 | | 🟠 橙 | 提交中 / 同步中 | | 🟢 绿 | 操作成功 / 全部装完 | | 🔴 红 | 错误(无效码 / 超限 / 提交失败) | | 🟡 琥珀 | 警告(箱号重复 / 编辑中) | --- ## 四、场景状态清单 | # | 场景 | 通知条 | 扫码条 | 列表 | 输入行 | 状态栏点 | |---|---|---|---|---|---|---| | 1 | 等待扫码 | 无 | 灰色等待 | 空 | 全禁用 | 🔵 | | 2 | 已扫码(无历史分配) | 无 | 绿色已识别 | 空 | 自动填充,可编辑 | 🔵 | | 3 | 已扫码 + 已有分配记录 | 无 | 绿色已识别 | 显示分配行 | 自动填充下一箱 | 🔵 | | 4 | 已分配行 — 编辑中 | 无 | 绿色已识别 | 目标行琥珀背景 + 输入 | 正常 | 🟡 | | 5 | 已分配行 — 删除确认 | 无 | 绿色已识别 | 目标行红背景 + 确认条 | 正常 | 🔴 | | 6 | 正在提交 | 无 | 绿色已识别 | 正常 | 全禁用 + loading | 🟠 | | 7 | 箱号重复 | 🟡 琥珀警告 | 绿色已识别 | 正常 | 箱号框红框,确认禁用 | 🟡 | | 8 | 数量超限 | 🔴 红色警告 | 绿色已识别 | 正常 | 数量框红框,确认禁用 | 🔴 | | 9 | 全部装箱完毕 | 🟢 绿色提示 | 绿色已识别 | 显示已分配明细 | 全禁用,进度条全绿 | 🟢 | | 10 | 自动同步中 | 🟠 同步 + 🟡 忽略 | 绿色已识别 | 正常,不可操作 | 全禁用 | 🟠 | --- ## 五、垂直空间节省汇总 | 区块 | v1 高度 | v2 高度 | 节省 | |---|---|---|---| | AppBar | ~52px | 44px | **8px** | | 扫码区 | ~52px | 38px | **14px** | | 排产信息 | ~80px(两块) | ~52px(合并)| **28px** | | 已分配行/条 | ~52px/条 | 40px/条 | **12px/条** | | 通知条 | ~36px | ~30px | **6px/条** | | 操作行(返回) | ~48px | 0(已移除)| **48px** | | 状态栏 | ~38px | 28px | **10px** | > 固定区域合计节省约 **114px**,相当于屏幕高度约 1/7,可多展示约 **2~3 条**已分配记录。 --- ## 六、与多码凑箱的设计统一点 以下组件与多码凑箱在样式、尺寸、行为上完全一致,无差异: - AppBar 高度与 Pill 组件(颜色区分模式) - 通知条(Notice Banner)的结构与色彩语义 - 已分配/已装入列表的行高、彩色竖条、序号、操作按钮 - 行内编辑(输入框 + ✓/✕)与删除确认条 - 状态栏高度、圆点颜色语义 - 底栏的 loading 转圈形态 --- ## 七、不在本次范围内的改动 - 装箱详情页(`boxing_detail_page.dart`)布局不变 - 状态机逻辑(`_Phase` 枚举、`_applyAutoFill`、API 调用时机)不变 - 物理按键 P2 切换模式行为不变 - 所有字段数据来源(`BoxInfoResult`、`saveBoxRecord` 等 API)不变