From 4810b444525fe8aefa8764ff9645270f443e03c8 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 28 Aug 2026 13:54:38 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 1 + README.md | 1 + src/api/receiving-adapter.js | 11 +++++++- src/pages/operation/operation.vue | 33 ++++++++++++++++------ tests/multi-plan-receiving.test.mjs | 43 ++++++++++++++++++++++++++--- tests/project-contract.test.mjs | 9 ++++-- 6 files changed, 81 insertions(+), 17 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4e0f08d..a4dcfa6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -50,6 +50,7 @@ ## 海外业务接口边界 - `src/api/inbound.js` 已接入待卸柜候选、柜详情/prepare、current 恢复、三类照片签收、统一箱码定位入仓码、实物托盘解析、FBA bulk/OVERSEAS carton 收货及整柜完成;FBA bulk 不提交 `skuCode`,库存分配由服务端按计划明细完成;响应与 404/409 判定集中在 `src/api/receiving-adapter.js`,双 Token 刷新与海外 401 单次重放由 `src/api/overseas.js` 统一处理。 +- 待卸柜候选保留服务端返回的未齐全柜并严格消费 `allPlansReady`、`operable`、`blockReason`、`plannedArrivalAt` 与柜级计划统计;`operable=false` 只能查看只读摘要,不得调用 prepare。候选顺序沿用服务端计划到仓时间排序,前端不得用入仓码/计划数组长度自行推导就绪或把预计到港冒充计划到仓。 - `src/api/pallet.js` 只调用 Lastleg 托盘专用 PDA Controller;前端提交服务端扫码返回的 `palletVersion`、`positionVersion` 和随机幂等键,不提交客户、仓库或库位标识。409 后必须重新扫码获取最新版本,禁止用旧库存快照继续作业。 - 请求身份和资源范围只取 Token 与 current 会话;前端不得提交 `customerId`、`planNo`、`allocationId`、`warehouseId` 或 `locationId`。409 必须引导账号恢复当前柜,完成前不得切柜。 - 签收照片固定为三个角色且每个角色只有一个当前文件;上传成功后使用服务端 `downloadPath` 在当前会话内鉴权读取。更换失败时保留原 `fileId` 和可提交状态,无原图的失败槽不得计入 `photosReady`;本地临时路径仅用于本次设备预览,不作为跨会话文件事实。 diff --git a/README.md b/README.md index 6683547..5fa07f4 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ npm run build:app - 已复用并内置:登录壳、PDA 样式、扫码广播、声音反馈、导航、网络检测、图标及 `uni_modules`。 - 已隔离:国内集装箱拣货、装柜证据、国内 Firstleg API、国内任务状态和国内本地草稿。 - 入仓页面已接待卸柜候选、柜详情与账号锁柜、三类角色照片签收、current 恢复、统一箱码与既有物理托盘解析、FBA 按箱数和 OVERSEAS 逐箱收货、逐入仓码核平及整柜完成的真实 API;收货页不预列柜内入仓码,箱码解析成功后只显示本次命中的入仓码;409 会引导返回当前柜,错误会保留业务码、requestId 与 traceId。 +- 候选列表同时显示已齐全与未齐全柜,展示计划到仓时间、总订单、入仓码、已生成计划、未操作和缺入仓码数量;未齐全柜置灰但可查看服务端阻断原因,只有服务端 `allPlansReady=true && operable=true` 才能 prepare。 - 托盘管理已接 `/api/pda/v1/last-leg/pallet-operations/**`:支持扫描查询当前仓实物托盘及库存内容,并按服务端版本执行组托、拆托、换托和解绑;不同目的仓不能合托,冻结或处理中的库存由服务端拒绝。 - 入仓请求不手填客户、计划、分配、仓库或库位标识;身份与当前柜范围由 Token、Gateway 和服务端会话确定。页面同时支持 PDA 广播扫码与 H5 人工输入。 - 登录、恢复和刷新会 fail-closed 校验国内/海外双 Token 的同一平台操作主体、`OVERSEAS_WAREHOUSE_PDA_OPERATOR`、`lastleg:pda:operate` 及同一冻结海外仓;并发海外 401 共享一次国内 refresh,校验完成后原子替换双 Token并将原请求或照片上传重放一次。 diff --git a/src/api/receiving-adapter.js b/src/api/receiving-adapter.js index 0249dc8..7b1cf6d 100644 --- a/src/api/receiving-adapter.js +++ b/src/api/receiving-adapter.js @@ -15,14 +15,23 @@ export function normalizeReceivingInbound(value = {}) { export function normalizeReceivingCandidate(value = {}) { return { ...value, + sourceContainerBookingId: typeof value.sourceContainerBookingId === 'string' ? value.sourceContainerBookingId.trim() : '', containerNo: String(value.containerNo || '').trim(), + plannedArrivalAt: typeof value.plannedArrivalAt === 'string' && value.plannedArrivalAt.trim() ? value.plannedArrivalAt.trim() : null, + totalOrderCount: number(value.totalOrderCount), planCount: number(value.planCount), inboundCodeCount: number(value.inboundCodeCount), + missingInboundCodeCount: number(value.missingInboundCodeCount), + plannedInboundCodeCount: number(value.plannedInboundCodeCount), + pendingPlanCount: number(value.pendingPlanCount), destinationCodes: Array.isArray(value.destinationCodes) ? value.destinationCodes.filter(Boolean) : [], plannedPalletCount: number(value.plannedPalletCount), totalPackages: number(value.totalPackages), receivedPackages: number(value.receivedPackages), - currentAccount: value.currentAccount === true + currentAccount: value.currentAccount === true, + allPlansReady: value.allPlansReady === true, + operable: value.operable === true, + blockReason: typeof value.blockReason === 'string' ? value.blockReason.trim() : '' } } diff --git a/src/pages/operation/operation.vue b/src/pages/operation/operation.vue index 964555c..964f5ee 100644 --- a/src/pages/operation/operation.vue +++ b/src/pages/operation/operation.vue @@ -12,17 +12,30 @@ {{ candidateError.message || '待卸货集装箱加载失败' }}code={{ candidateError.code }}requestId={{ candidateError.requestId }}traceId={{ candidateError.traceId }} 正在刷新待卸货集装箱… 暂无待卸货集装箱 - - {{ item.containerNo }}{{ statusLabel(item.status) }}{{ item.currentAccount ? '继续' : '详情' }} › - {{ item.inboundCodeCount }}入仓码{{ item.totalPackages }}箱{{ item.plannedPalletCount }}计划托盘{{ item.destinationCodes?.length || 0 }}目的仓 + + {{ item.containerNo }}计划到仓:{{ formatPlannedArrival(item.plannedArrivalAt) }}{{ item.operable ? statusLabel(item.status) : '待齐全' }}{{ item.operable ? (item.currentAccount ? '继续' : '详情') : '只读' }} › + {{ item.totalOrderCount }}总订单{{ item.inboundCodeCount }}入仓码{{ item.planCount }}已生成计划{{ item.pendingPlanCount }}未操作 + 已生成 {{ item.planCount }} 个入库计划,{{ item.pendingPlanCount }} 个未操作 + {{ item.blockReason || '当前柜入库计划尚未齐全' }} 仓码:{{ item.destinationCodes.join(' / ') }}