diff --git a/docs/demos/storage-facility-batch-outbound-demo.html b/docs/demos/storage-facility-batch-outbound-demo.html new file mode 100644 index 00000000..13b8c131 --- /dev/null +++ b/docs/demos/storage-facility-batch-outbound-demo.html @@ -0,0 +1,666 @@ + + + + + + 库位管理 · 批量出库 Demo + + + +
+
+

库位管理 · 批量出库交互 Demo

+

先点下方方案切换预览,再在货架上试操作。推荐方案 A(工具栏进入多选模式)。

+
+ +
+
+ 推荐 · A +

工具栏「批量出库」→ 多选格子

+

点按钮进入选择模式,只可选占用格;确认后一次性出库。空格不可选。

+
+
+ B +

格子常驻勾选框

+

占用格左上角始终显示勾选框,选完后点工具栏「出库」。更直接,但日常浏览稍吵。

+
+
+ C +

框选 / 起止区间

+

拖拽或选起止格批量勾选同盒连续占用格。适合密集出库,交互更重。

+
+
+ +
+ + +
+
+

A区冷库 / 1层 / 盒-01

+
+ 总数 12 + · 空闲 4 + · 占用 8 +
+
+ +
+ +
+ +
+ 批量出库模式 + 请勾选要出库的占用储物格,空格不可选。 +
+ +
+ +
+ +
+ 当前方案 A:先点「批量出库」进入选择模式,再点占用格勾选,最后确认出库。 +
+
+
+
+ +
+ +
+
+

批量出库确认

+

确认将选中储物格中的物品出库?

+
+
+ + +
+
+
+ + + + diff --git a/docs/superpowers/specs/2026-07-28-storage-facility-batch-outbound-design.md b/docs/superpowers/specs/2026-07-28-storage-facility-batch-outbound-design.md new file mode 100644 index 00000000..f0e01b4a --- /dev/null +++ b/docs/superpowers/specs/2026-07-28-storage-facility-batch-outbound-design.md @@ -0,0 +1,116 @@ +# 库位管理:货架批量出库设计 + +> 日期: 2026-07-28 +> 状态: 已确认 +> 范围: web-admin 库位管理 + 货架列表字段小幅 enrichment(无新批量出库 API) +> 参考 Demo: `docs/demos/storage-facility-batch-outbound-demo.html`(方案 B) + +## 1. 背景与目标 + +当前库位管理中,储物格点击仅打开「储物格明细」弹窗,出库须在弹窗「在库物品」操作列逐条完成,大批量出库效率低。 + +**目标**:在货架界面直接勾选占用储物格,工具栏一键批量出库,减少进出弹窗次数。 + +**非目标**: + +- 不新增后端批量出库事务 API(可后续升级) +- 不提供「全选占用」 +- 不改小程序端 +- 不改变明细弹窗内单条「出库」行为 + +## 2. 已确认决策 + +| 项 | 决策 | +|----|------| +| 交互形态 | 方案 B:占用格左上角常驻勾选框 | +| 点格 vs 点框 | 勾选框切换选中;格子其它区域仍打开储物格明细 | +| 二次确认 | 需要:确认框列出已选格子编码 + 物品名称 | +| 全选 | 不要,仅逐格勾选 | +| 出库实现 | 方案 1:前端串行调用现有 `fetchRemoveOccupancy` | +| 占用 ID | 货架列表 enrichment 增加 `storedOccupancyId` | + +## 3. 界面与交互 + +### 3.1 格子 + +- 占用格(`slotStatus === '占用'` 且存在在库占用)左上角常驻勾选框;空格不显示勾选框、不可选。 +- 勾选框 `@click.stop`:切换选中;点格子其它区域:`handleOpenOccupancyDialog`(现有行为)。 +- 选中态:勾选框主色填充 + 格子浅绿描边(Fresh Mint:`--primary` / `#ecfdf5` / `#a7f3d0`)。 +- 删除按钮(×)行为不变,继续 `@click.stop`。 + +### 3.2 工具栏(叶子节点且已有格子时) + +顺序(符合列表工具栏「已选在前」约定): + +1. 「已选 N 项」文案 +2. 「出库已选」主按钮(`type="primary"`,N=0 时禁用;执行中 loading) +3. 现有「批量生成格子 / 清空格子」等按钮 + +不提供「全选占用」「清空选择」独立按钮(取消勾选即可;切换节点会清空选择)。 + +### 3.3 确认与结果 + +- 点击「出库已选」→ `ElMessageBox.confirm`(与现有单条出库确认一致),正文列出每项:`格子编码` + `物品名称`(无名称则物品编码);条目过多时正文可截断并注明「等共 N 项」。 +- 确认后串行出库;成功提示「出库成功,共 N 项」。 +- 刷新当前叶子节点格子列表与左侧占用统计;清空选择。 + +### 3.4 选择生命周期 + +- 切换左侧树节点、执行「清空格子」后:清空选择。 +- 筛选关键词变化:保留仍在当前可见且仍占用的选中项;不可见或已空的自动剔除。 +- 单格在明细弹窗内出库成功后:若该格在选中集合中,从集合移除并刷新。 + +## 4. 数据流与错误处理 + +### 4.1 占用 ID + +现有 `enrich_slots_with_stored_cell_products` 仅附带展示字段,不含占用记录 id。 +单条出库接口 `PUT /web/admin/storage-slot-occupancies/{occupancy_id}/remove` 需要 occupancy id。 + +**改动**:enrichment 时写入 `storedOccupancyId = occ.id`(当前 `occupancy_status == stored` 的那条;一格一物)。 + +前端选中结构示例: + +```ts +{ slotId, occupancyId, slotCode, itemName } +``` + +仅当 `storedOccupancyId` 存在时允许勾选。 + +### 4.2 执行流程 + +1. 用户勾选 → `selectedMap`(key=`slotId`) +2. 确认框展示列表 +3. 按选中顺序串行 `await fetchRemoveOccupancy(occupancyId)` +4. 全部成功:刷新货架 + 统计;清空选择;成功提示 +5. 过程中主按钮 loading,防止重复提交 + +### 4.3 错误处理 + +- 第 k 条失败:停止后续请求;已成功的 k-1 条保留出库结果;提示「已出库 M 项,第 M+1 项失败:…」(或接口返回文案);刷新货架;清理选中中已不存在/已空的项。 +- 用户取消确认:无请求。 +- 不做事务级「全成或全败」(若业务后续强制要求,另开批量 API 变更)。 + +## 5. 改动清单 + +| 文件 | 改动 | +|------|------| +| `backend/app/crud/storage_occupancy.py` | `enrich_slots_with_stored_cell_products` 增加 `storedOccupancyId` | +| `web-admin/src/views/operations/storage-facility/index.vue` | 勾选 UI、工具栏、确认与串行出库、选中态样式、生命周期清理 | +| `docs/demos/storage-facility-batch-outbound-demo.html` | 参考用 Demo(非上线依赖) | + +## 6. 验收标准 + +1. 占用格有勾选框,空格无;点框选中,点格身仍开明细。 +2. N>0 时可点「出库已选」;确认框列出编码 + 名称。 +3. 确认后逐条出库,货架与左侧统计刷新,选择清空。 +4. 中途失败:已成功保留,提示已出库数与失败原因,货架刷新。 +5. 切换树节点后选择清空;明细弹窗单条出库行为不变。 +6. 货架接口响应中占用格含 `storedOccupancyId`。 + +## 7. 测试要点 + +- 手动入库「其他」物品与细胞产品占用格均可勾选并出库。 +- 仅空格的叶子节点:无勾选框,「出库已选」禁用。 +- 筛选命中部分占用格时,仅能勾选可见占用格。 +- 出库后格子变为空,勾选框消失。