Files
zkxw/docs/superpowers/specs/2026-07-28-storage-facility-batch-outbound-design.md
T
zlwuandCursor 45c2e3df01 docs: add storage facility batch outbound design and demo
Capture confirmed UI (always-on checkboxes) and serial remove via existing occupancy API for implementation planning.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 19:08:43 +08:00

117 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 库位管理:货架批量出库设计
> 日期: 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. 测试要点
- 手动入库「其他」物品与细胞产品占用格均可勾选并出库。
- 仅空格的叶子节点:无勾选框,「出库已选」禁用。
- 筛选命中部分占用格时,仅能勾选可见占用格。
- 出库后格子变为空,勾选框消失。