From 37d399752dcfbd91954bfd8cabdc1bc030eb012c Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 17 Aug 2026 17:49:08 +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 --- pages/picking/picking.vue | 25 +++++++--- pages/tasks/tasks.vue | 70 +++++++++++++++++++-------- styles/pda.scss | 27 ++++++++--- tests/page-contract.test.mjs | 3 +- tests/picking-evidence-stage.test.mjs | 3 ++ 5 files changed, 91 insertions(+), 37 deletions(-) diff --git a/pages/picking/picking.vue b/pages/picking/picking.vue index d9695d2..de6e860 100644 --- a/pages/picking/picking.vue +++ b/pages/picking/picking.vue @@ -11,7 +11,7 @@ - + + + + + {{ slot.label }} + {{ evidenceEntries(slot.type).length ? evidenceEntries(slot.type).length + ' 张' : '待拍摄' }} + + + + + + 图片处理中 + {{ photo.fileName || '已记录' }} + + + + 现场拍摄后自动上传,可继续追加 {{ evidenceUploadState(slot.type) }} 本地暂存,待自动上传 - diff --git a/pages/tasks/tasks.vue b/pages/tasks/tasks.vue index b8a79ec..ac4c47a 100644 --- a/pages/tasks/tasks.vue +++ b/pages/tasks/tasks.vue @@ -3,19 +3,28 @@ - 待处理任务 - + + 待处理任务 + {{ loading ? '正在同步' : `共 ${tasks.length} 个可处理任务` }} + + {{ error }} 正在加载真实任务... 暂无可领取的拣货任务。请确认预装已补充集装箱号、已关联放舱订舱且预装已确认。 {{ notice }} - - 集装箱号 {{ task.currentContainerNo }}{{ statusLabel(task.workflowStatus) }} - 柜次号 {{ task.cabinetNo }} - {{ task.displayNo || '未命名订单' }} - {{ task.warehouseName || (task.warehouseId ? `仓库 ${task.warehouseId}` : '缺少仓库信息') }} · 待处理 {{ task.pendingItemCount ?? task.itemCount ?? 0 }} 项 - + + {{ toast.message }} @@ -73,19 +82,38 @@ diff --git a/styles/pda.scss b/styles/pda.scss index be05608..d809741 100644 --- a/styles/pda.scss +++ b/styles/pda.scss @@ -259,6 +259,10 @@ padding: 1px 0 104px; } + .work-content.evidence-active { + padding-bottom: 1px; + } + .box-select-wrap { position: relative; z-index: 5; @@ -1148,19 +1152,27 @@ .sync-state.ready { color: $success; background: #e8f8ef; } .sync-state.error { color: $danger; background: #fff0f0; } .sync-state.loading { color: #8a5a00; background: #fff7df; } - .evidence-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 12px; } - .evidence-card { min-height: 86px; padding: 10px; border: 1px dashed #b8c9df; border-radius: 8px; background: #f8fafc; } - .evidence-card.filled { border-style: solid; border-color: #69b88a; background: #f0fbf4; } + .evidence-grid { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; } + .evidence-card { padding: 10px; border: 1px solid #d7e1ed; border-radius: 9px; background: #f8fafc; } + .evidence-card.filled { border-color: #a7d6ba; background: #f4fbf6; } + .evidence-card-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; } + .evidence-card-title { display: flex; min-width: 0; align-items: center; gap: 7px; } .evidence-label { display: block; color: $text; font-size: 12px; font-weight: 700; } - .evidence-file-row { display: flex; align-items: center; gap: 7px; min-width: 0; margin-top: 7px; } - .evidence-thumbnail { flex: 0 0 48px; width: 48px; height: 48px; border-radius: 6px; background: #e7edf5; } - .evidence-file-detail { flex: 1; min-width: 0; } - .evidence-file { display: block; overflow: hidden; margin-top: 5px; color: $text-secondary; font-size: 10px; line-height: 15px; text-overflow: ellipsis; white-space: nowrap; } + .evidence-count { padding: 2px 6px; border-radius: 99px; color: $text-secondary; font-size: 10px; line-height: 16px; background: #e9eef5; } + .evidence-count.complete { color: #087443; background: #dff4e7; } + .evidence-photo-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 9px; } + .evidence-photo-item { position: relative; min-width: 0; padding: 4px; border: 1px solid #dbe5ef; border-radius: 8px; background: #ffffff; } + .evidence-thumbnail { display: flex; width: 100%; height: 68px; align-items: center; justify-content: center; border-radius: 6px; color: $text-secondary; font-size: 9px; line-height: 13px; text-align: center; background: #e7edf5; } + .evidence-thumbnail-placeholder { box-sizing: border-box; padding: 6px; } + .evidence-file { display: block; overflow: hidden; margin-top: 4px; padding: 0 2px; color: $text-secondary; font-size: 9px; line-height: 14px; text-overflow: ellipsis; white-space: nowrap; } + .evidence-void-btn { position: absolute; top: 8px; right: 8px; min-width: 40px; height: 40px; padding: 0 7px; border: 0; border-radius: 20px; color: #ffffff; font-size: 10px; line-height: 40px; background: rgba(185, 28, 28, 0.9); } + .evidence-empty-hint { display: block; margin-top: 7px; color: $text-secondary; font-size: 10px; line-height: 15px; } .evidence-upload-state { display: block; margin-top: 5px; color: $text-secondary; font-size: 10px; line-height: 15px; } .evidence-upload-state.uploading, .evidence-upload-state.pending { color: #174d91; } .evidence-upload-state.failed { color: $danger; } .evidence-upload-state.succeeded { color: $success; } .evidence-btn { min-height: 40px; margin-top: 8px; padding: 0 9px; border: 1px solid #9db7d9; border-radius: 7px; color: #174d91; font-size: 12px; line-height: 40px; background: #ffffff; } + .evidence-add-btn { flex-shrink: 0; min-width: 78px; min-height: 40px; margin-top: 0; line-height: 40px; } .evidence-retry-btn { min-height: 40px; margin-top: 6px; padding: 0 9px; border: 1px solid $danger; border-radius: 7px; color: $danger; font-size: 12px; line-height: 40px; background: #fff5f4; } .seal-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; } .seal-input { flex: 1; height: 42px; box-sizing: border-box; padding: 0 10px; border: 1px solid $border; border-radius: 7px; font-size: 12px; background: #f8fafc; } @@ -1206,6 +1218,7 @@ .pick-item-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); } .pick-btn-confirm { grid-column: 1 / -1; } .processed-actions { grid-template-columns: 1fr; } + .evidence-photo-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .submit-section { gap: 8px; width: calc(100% - 12px); padding-right: 8px; padding-left: 8px; } .submit-info { width: 96px; min-width: 96px; } } diff --git a/tests/page-contract.test.mjs b/tests/page-contract.test.mjs index 158195e..a9d956e 100644 --- a/tests/page-contract.test.mjs +++ b/tests/page-contract.test.mjs @@ -48,8 +48,9 @@ test('picking task list uses remote loading orders and never falls back to demo assert.match(tasks, /\['UNASSIGNED', 'IN_PROGRESS', 'AWAITING_REVIEW'\]\.includes\(task\.workflowStatus\)/) assert.match(tasks, /task\.workflowStatus === 'AWAITING_REVIEW' \|\| \(task\.assignmentVersion !== null/) assert.match(tasks, /暂无可领取的拣货任务/) - assert.match(tasks, /集装箱号 \{\{ task\.currentContainerNo \}\}/) + assert.match(tasks, /class="task-label">集装箱号<\/text>\{\{ task\.currentContainerNo \}\}/) assert.match(tasks, /柜次号 \{\{ task\.cabinetNo \}\}/) + assert.match(tasks, /button v-for="task in tasks"[\s\S]*?class="task-card"[\s\S]*?@tap="enterTask\(task\)"/) assert.match(tasks, /records\.filter\(\(task\) => this\.isTaskReady\(task\)\)/) assert.match(tasks, /isTaskReady\(task\)[\s\S]*?task\.recordStatus === 'ACTIVE'[\s\S]*?!task\.mergedIntoContainerBookingId/) assert.match(tasks, /records\.filter\(\(task\) => this\.isMergedTask\(task\)\)\.forEach\(\(task\) => this\.clearMergedTaskDraft\(task\)\)/) diff --git a/tests/picking-evidence-stage.test.mjs b/tests/picking-evidence-stage.test.mjs index 008a35c..49e5ae9 100644 --- a/tests/picking-evidence-stage.test.mjs +++ b/tests/picking-evidence-stage.test.mjs @@ -146,6 +146,9 @@ test('refresh preserves local photos for the same evidence identity and flushes test('evidence photos render thumbnails and support full-screen preview', () => { assert.match(page, /class="evidence-thumbnail" :src="evidencePreviewSource\(photo\)"/) + assert.match(page, /class="work-content" :class="\{ 'evidence-active': activeStage === 'evidence' && loadingStageReady \}"/) + assert.match(page, /class="evidence-photo-grid"/) + assert.match(page, /class="evidence-count"/) assert.match(page, /@tap="previewEvidencePhoto\(photo, slot\.type\)"/) assert.match(page, /evidencePreviewSource\(photo\)[\s\S]*?localPath[\s\S]*?fileUrl/) assert.match(page, /previewEvidencePhoto\(photo, type\)[\s\S]*?uni\.previewImage\([\s\S]*?current[\s\S]*?urls/)