feat(scan): 出库/借库扫码页接入草稿,切换单据不清空

交互
----
无需「暂停」按钮 —— 在下拉框切换单据这个动作本身就是暂停:
  切走 → 自动存当前单据的进度
  切回 → 自动恢复,并提示「已恢复上次的扫码进度(N 项)」
下拉框对扫到一半的单据显示橙色「已扫 N」徽标,不必逐个点开试。
提交成功后自动清除该单据的草稿。

修复的三个 bug
--------------
1) 切换时把 A 的内容存到了 B 名下
   v-model="selectedRequestId" 的 computed setter 会**先于** @change 把
   selectedRequest 改成新单,故 handleRequestChange 里读到的是新单。
   新增 activeRequestId ref 记录「界面上真正显示的是哪张单」,
   保存时显式传入离开的那张单的 ID。

2) 切回时把目标单的旧草稿删了
   原先写了「购物车为空则清除草稿」,但切换瞬间购物车必然为空,
   于是切回 A 时触发了清除。现改为空清单只跳过保存、不清除;
   清理由「提交成功」或「用户点清空列表」显式触发。

3) 恢复后名称/规格为空、出库数显示 NaN
   draftPayload 只存了 4 个字段(stock_id/source_table/sku/quantity),
   而购物车表格绑定的是 name/spec_model/available_quantity/out_quantity
   —— 全都没存。现保存完整快照,并在恢复时归一化
   (out_quantity ?? quantity)以兼容已存在的旧草稿。

补充:恢复后刷新实时库存
------------------------
草稿里的 available_quantity 是扫描那一刻的快照,跨时间恢复可能已过期
(期间别人出库/借出会消耗可用量)。恢复后复用 /alternatives 端点拉一次
实时可用量:数量超了会明确提示「N 项物料的实际库存已少于你扫的数量」,
避免工人扫满后到提交时才被后端拒绝。失败不阻断,沿用草稿快照。

另:离开页面(路由跳转)时存草稿并弹确认;beforeunload 用 sendBeacon
尽力保存(该路径无法带 Authorization 头,可能失败,但防抖保存已覆盖
绝大部分内容)。
This commit is contained in:
yueli
2026-09-10 17:21:24 +08:00
parent ec66c33b06
commit a4a9afb6db
3 changed files with 501 additions and 5 deletions

View File

@ -239,3 +239,55 @@ export function getMyRequests(params: {
params
})
}
// ==========================================
// 扫码草稿(出库/借库作业中途暂停用)
// ==========================================
export interface ScanDraftItem {
stock_id: number
source_table: string
sku?: string
quantity: number
}
/** 读取草稿:返回该用户在这张单上已扫的内容 */
export function getScanDraft(bizType: 'outbound' | 'borrow', requestId: number) {
return request({
url: '/v1/scan-draft',
method: 'get',
params: { biz_type: bizType, request_id: requestId }
})
}
/** 保存草稿:全量覆盖(提交的 items 即当前完整清单) */
export function saveScanDraft(
bizType: 'outbound' | 'borrow',
requestId: number,
items: ScanDraftItem[],
requestNo?: string
) {
return request({
url: '/v1/scan-draft',
method: 'post',
data: { biz_type: bizType, request_id: requestId, request_no: requestNo || '', items }
})
}
/** 清除草稿:提交成功后调用 */
export function clearScanDraft(bizType: 'outbound' | 'borrow', requestId: number) {
return request({
url: '/v1/scan-draft',
method: 'delete',
params: { biz_type: bizType, request_id: requestId }
})
}
/** 草稿概览:供单据下拉显示「已扫 N 项」进度徽标 */
export function getScanDraftOverview(bizType: 'outbound' | 'borrow') {
return request({
url: '/v1/scan-draft/overview',
method: 'get',
params: { biz_type: bizType }
})
}