From 81f63e5d26210ee82dce8dfb0d21646b18c3788c Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 23 Oct 2026 02:39:14 +0800 Subject: [PATCH] fix(pda): discard failed ordinary photo drafts --- pages/picking/picking.vue | 4 ++++ tests/picking-failure-recovery.test.mjs | 30 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/pages/picking/picking.vue b/pages/picking/picking.vue index 84fbd3a..6a563f2 100644 --- a/pages/picking/picking.vue +++ b/pages/picking/picking.vue @@ -1350,6 +1350,10 @@ this.showToast(type === 'SEAL' ? '带锁码照上传成功,封签号已保存' : '照片已上传并保存', 'success') } catch (error) { if (!this.isEvidenceContextActive(contextId, identity)) return + if (type !== 'SEAL') { + this.evidenceFiles = { ...this.evidenceFiles, [type]: (this.evidenceFiles[type] || []).filter(photo => photo.id || photo.localPath !== path) } + this.removeDraftPhoto(type, path) + } entry.status = 'FAILED'; entry.error = this.remoteFailureMessage(error, '照片上传失败,请重新操作') this.remoteError = entry.error } finally { if (this.isEvidenceContextActive(contextId, identity)) { this.evidenceUploading = false; this.evidenceQueueItems = this.evidenceQueueItems.map(item => ({ ...item })) } } diff --git a/tests/picking-failure-recovery.test.mjs b/tests/picking-failure-recovery.test.mjs index 58a0121..0490785 100644 --- a/tests/picking-failure-recovery.test.mjs +++ b/tests/picking-failure-recovery.test.mjs @@ -90,3 +90,33 @@ test('photo failure releases the page and another click uploads the current phot assert.equal(state.evidenceUploading, false); assert.equal(requests[1][3], 'new.jpg'); assert.equal(requests[1][2].sealNo, 'NEW') assert.notEqual(requests[1][2].operationId, requests[0][2].operationId) }) + +test('failed ordinary photo is removed from the visible and restored draft without deleting saved evidence', async () => { + const uploadMethod = page.slice(page.indexOf('async queueEvidenceUpload('), page.indexOf('async saveSealNo(')) + const draftMethods = page.slice(page.indexOf('evidenceDraftKey(identity)'), page.indexOf('requireEvidenceCapture() {')) + const behavior = new Function('isRemoteReady', 'uploadEvidenceFile', 'return ({' + draftMethods + uploadMethod + '})')( + () => true, async () => { throw new Error('upload failed') } + ) + const saved = { id: 'saved-photo', fileId: 'saved-file', localPath: 'saved.jpg' } + const failed = { localPath: 'failed.jpg', uploadStatus: 'PENDING' } + const seal = { localPath: 'seal.jpg', uploadStatus: 'PENDING' } + const state = { + ...behavior, evidenceUploading: false, evidenceReadOnly: false, + evidenceIdentity: { taskId: 'task', warehouseId: 'warehouse' }, evidenceContextId: 1, + evidenceQueueItems: [], evidenceDrafts: {}, sealNo: 'SEAL-A', + evidenceFiles: { PHOTO_STEP_1: [saved, failed], SEAL: [seal] }, + validEvidenceEntries: () => [saved], isEvidenceContextActive: () => true, + remoteFailureMessage: error => error.message, showToast() {} + } + state.rememberEvidenceDraft() + await state.queueEvidenceUpload('PHOTO_STEP_1', 'failed.jpg') + assert.deepEqual(state.evidenceFiles.PHOTO_STEP_1, [saved]) + assert.equal(state.evidenceUploading, false) + assert.equal(state.remoteError, 'upload failed') + state.restoreEvidenceDraft() + assert.equal(state.evidenceFiles.PHOTO_STEP_1, undefined) + assert.deepEqual(state.evidenceFiles.SEAL, [seal]) + await state.queueEvidenceUpload('SEAL', 'seal.jpg', 'SEAL-A') + assert.deepEqual(state.evidenceFiles.SEAL, [seal]) + assert.equal(state.evidenceUploading, false) +})