Capture confirmed UI (always-on checkboxes) and serial remove via existing occupancy API for implementation planning. Co-authored-by: Cursor <cursoragent@cursor.com>
117 lines
5.1 KiB
Markdown
117 lines
5.1 KiB
Markdown
# 库位管理:货架批量出库设计
|
||
|
||
> 日期: 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. 测试要点
|
||
|
||
- 手动入库「其他」物品与细胞产品占用格均可勾选并出库。
|
||
- 仅空格的叶子节点:无勾选框,「出库已选」禁用。
|
||
- 筛选命中部分占用格时,仅能勾选可见占用格。
|
||
- 出库后格子变为空,勾选框消失。
|