From 54e49e24267cea247f0f10234c98b919523cb0d7 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Thu, 22 Oct 2026 23:06:06 +0800 Subject: [PATCH] fix: complete October 22 workflow feedback and request failure recovery --- docs/business-index.md | 2 +- src/api/dispatch-loading-documents.js | 1 - src/api/overseas.js | 14 +- src/components/DispatchLoadingDocuments.vue | 75 +++----- src/components/RelabelPalletWork.vue | 6 +- src/components/ReturnBoxMergeWork.vue | 7 +- src/components/ReturnRelabelPackWork.vue | 4 +- src/pages/dispatch/dispatch.vue | 150 +++++++++++---- src/pages/move/move.vue | 4 +- src/pages/outbound/outbound.vue | 8 +- src/pages/pallet/pallet.vue | 2 +- src/pages/relabel/relabel.vue | 20 +- src/pages/return-packing/return-packing.vue | 4 +- src/pages/return-receipt/return-receipt.vue | 78 ++++---- src/pages/stocktake/stocktake.vue | 10 +- .../warehouse-transfer/warehouse-transfer.vue | 12 +- src/stores/fulfillment.js | 58 +----- src/stores/warehouse-work.js | 33 ++-- tests/dispatch-loading-documents.test.mjs | 79 ++++---- tests/dispatch-presentation.test.mjs | 30 +++ tests/dispatch-workflow.test.mjs | 174 +++++++----------- tests/fulfillment-workflows.test.mjs | 13 +- tests/overseas-request.test.mjs | 43 +++++ tests/project-contract.test.mjs | 4 +- tests/return-box-merge-work.test.mjs | 35 +++- tests/return-receipt-api.test.mjs | 2 +- tests/return-receipt-page.test.mjs | 68 ++++++- tests/warehouse-workflows.test.mjs | 7 +- 28 files changed, 530 insertions(+), 413 deletions(-) create mode 100644 tests/dispatch-presentation.test.mjs diff --git a/docs/business-index.md b/docs/business-index.md index 419844c..aff014f 100644 --- a/docs/business-index.md +++ b/docs/business-index.md @@ -17,7 +17,7 @@ | 海外仓工作台与作业入口 | `src/pages/home/home.vue` | `src/data/overseas-workbench.js` 是分组与作业可用性入口;首页直接进入各作业,页面刷新后返回首页;首页通过 `/api/pda/v1/last-leg/receiving-containers/warehouse-profile` 读取 Token 绑定仓的中文主档名称 | | 中英西语言设置 | `src/i18n/index.js`、`src/i18n/locales/`、`src/pages/profile/profile.vue` | 个人中心可选择并持久化 `zh-CN`、`en`、`es`;当前业务翻译资源仍为空,页面业务文案继续使用中文,不得把语言选择入口误报为全量翻译完成 | | 柜号签收、照片与入仓真实作业 | `src/pages/operation/operation.vue`、`src/components/ReceivingSessionSummary.vue`、`src/api/inbound.js`、`src/api/receiving-adapter.js`、`src/api/overseas.js`、`src/stores/receiving.js` | 签收前展开显示国内空仓、半仓、满仓、锁仓和带锁码五类整柜只读照片,收货中折叠查看,单图加载失败只允许重试且不阻断拆柜;海外三个固定照片角色各一张,支持现场拍照、鉴权预览及更换失败保留原图;多计划同柜直接展示服务端 `assigned/mergeAllowed/urgent/mergeHint`,合托明确为现场可选而非完成门禁;扫码实收确认计划生成阶段已预留的真实托盘和库位,校验卡展示预留库位编码及 `A0` 共享溢出位提示,不在设备端重新分配。Backend `lastleg-service/inboundplan/pda/controller/ReceivingContainerController.java`、`ReceivingContainerService.java`,公网前缀 `/api/pda/v1/last-leg/receiving-containers/**` | -| 退货入库签收与合箱 | `src/pages/return-receipt/return-receipt.vue`、`src/pages/return-packing/return-packing.vue`、`src/api/return-receipt.js`、`src/api/return-packing.js`、`src/stores/warehouse-work.js` | 签收优先扫描退货单号,也可扫描 SKU 后选择候选退货单,按本包实际 SKU 数量生成退货箱与计费批次;合箱只选择同客户已完成退货单的可用库存并录入新箱箱规;公网前缀 `/api/pda/v1/last-leg/return-receipts/**`、`/api/pda/v1/last-leg/return-inventory/**` | +| 退货入库签收与合箱 | `src/pages/return-receipt/return-receipt.vue`、`src/pages/return-packing/return-packing.vue`、`src/api/return-receipt.js`、`src/api/return-packing.js`、`src/stores/warehouse-work.js` | 签收优先扫描退货单号,也可扫描 SKU 后选择候选退货单,按本包实际 SKU 数量生成退货箱与计费批次;刷新时服务端实收已变化须清空旧实物输入,未变化保留可编辑草稿;合箱只选择同客户已完成退货单的可用库存并录入新箱箱规;公网前缀 `/api/pda/v1/last-leg/return-receipts/**`、`/api/pda/v1/last-leg/return-inventory/**` | | 退货箱内清点 | `src/pages/return-counting/return-counting.vue`、`src/api/return-counting.js` | 扫描箱号或托盘号定位清点任务;各箱 SKU 汇总与签收数量核平,支持恢复当前任务;页面注册见 `src/pages.json` | | 仓储转运测量、打托与标签 | `src/pages/warehouse-transfer/warehouse-transfer.vue`、`src/api/warehouse-transfers.js` | 工作台键 `warehouseTransfer`;候选→详情→逐托测量草稿→生成新托盘号→扫码绑定→照片与完成打托。API 模块路径 `/pda/v1/last-leg/warehouse-transfers` 经统一海外请求层处理;不是 Admin 转运审核或排车转派送。回归 `tests/warehouse-transfer-api.test.mjs` | | 托盘管理真实作业 | `src/pages/pallet/pallet.vue`、`src/api/pallet.js` | 扫码查询托盘内容,按服务端返回的托盘/库存版本执行组托、拆托、换托和解绑;公网前缀 `/api/pda/v1/last-leg/pallet-operations/**` | diff --git a/src/api/dispatch-loading-documents.js b/src/api/dispatch-loading-documents.js index f355e9d..07b188d 100644 --- a/src/api/dispatch-loading-documents.js +++ b/src/api/dispatch-loading-documents.js @@ -21,6 +21,5 @@ export function normalizeLoadingDocuments(value, no) { } export async function getLoadingDocuments(no) { return normalizeLoadingDocuments(await overseasRequest('GET', path(no)), no) } export function uploadLoadingPhoto(no, slot, filePath, key) { return overseasUpload(`${slotPath(no, slot)}/uploads?idempotencyKey=${encodeURIComponent(key)}`, filePath) } -export function recoverLoadingPhoto(no, key) { return overseasRequest('GET', `${path(no)}/uploads/${encodeURIComponent(key)}`) } export async function bindLoadingPhoto(no, slot, body) { return normalizeLoadingDocuments(await overseasRequest('PUT', slotPath(no, slot), body), no) } export function readLoadingPhoto(no, photo) { return overseasDownload(`${slotPath(no, photo.slot)}/files/${encodeURIComponent(photo.fileId)}/content`, { expectedContentTypePrefix: 'image/' }) } diff --git a/src/api/overseas.js b/src/api/overseas.js index 3966a6f..1f618eb 100644 --- a/src/api/overseas.js +++ b/src/api/overseas.js @@ -135,12 +135,22 @@ function rawUpload(path, filePath, name, token) { const request = new XMLHttpRequest() request.open('POST', url) request.setRequestHeader('Authorization', `Bearer ${token}`) + request.timeout = 60000 request.onload = () => resolve({ statusCode: request.status, data: request.responseText, header: {} }) request.onerror = () => reject(new Error('海外作业文件上传失败')) + request.ontimeout = () => reject(new Error('照片上传超时,请重试')) + request.onabort = () => reject(new Error('照片上传已中断,请重试')) request.send(form) }) - const response = await fetch(url, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: form }) - return { statusCode: response.status, data: await response.text(), header: Object.fromEntries(response.headers.entries()) } + const controller = new AbortController() + const timeout = setTimeout(() => controller.abort(), 60000) + try { + const response = await fetch(url, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: form, signal: controller.signal }) + return { statusCode: response.status, data: await response.text(), header: Object.fromEntries(response.headers.entries()) } + } catch (cause) { + if (controller.signal.aborted) throw new Error('照片上传超时,请重试') + throw cause + } finally { clearTimeout(timeout) } }) .catch((cause) => { throw Object.assign(new Error(cause.message || '海外作业文件上传失败'), { network: true, uploadUrl: url }) }) } diff --git a/src/components/DispatchLoadingDocuments.vue b/src/components/DispatchLoadingDocuments.vue index b77428f..3db4448 100644 --- a/src/components/DispatchLoadingDocuments.vue +++ b/src/components/DispatchLoadingDocuments.vue @@ -8,21 +8,20 @@ 可边装车边上传;确认装车完成且照片齐全后自动进入派送中。 上传并保存 5 张装车照片后,本车自动进入派送中。 {{ error.message }}requestId:{{ error.requestId }}traceId:{{ error.traceId }} - 有装车照片尚未确认保存。 {{ snapshot?.photos.some(item => item.slot === slot) ? '✓' : index + 1 }} - 装车照片 {{ index + 1 }}{{ snapshot?.photos.some(item => item.slot === slot) ? '已保存 1 张' : '待上传' }} + {{ slotLabels[slot] }}{{ snapshot?.photos.some(item => item.slot === slot) ? '已保存 1 张' : '待上传' }} - + - - - 查看大图 + + + 查看大图 @@ -32,28 +31,18 @@