fix: complete October 22 workflow feedback and request failure recovery
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
<view class="task-summary-card">
|
||||
<view class="summary-head"><text class="inbound-code">{{ task.inboundCode || '—' }}</text><text class="status">{{ statusLabel }}</text></view>
|
||||
<text class="warehouse-summary">{{ task.warehouseName || '仓库未关联' }}</text>
|
||||
<text class="warehouse-summary">当前票 · {{ task.customerName || '客户未关联' }}</text>
|
||||
<view class="compact-metrics">
|
||||
<text><strong>{{ task.totalCartons || 0 }}</strong>总箱</text>
|
||||
<text><strong>{{ task.countedCartons || 0 }}</strong>清点</text>
|
||||
@@ -60,7 +59,7 @@
|
||||
</view>
|
||||
|
||||
<view class="section-card">
|
||||
<view class="section-heading"><view><text class="section-title">2. 托盘操作</text><text class="section-desc">直接扫描托盘码,只显示当前操作的托盘;待绑托箱扫描目标托盘后批量归托</text></view><button class="text-button" :disabled="loading" @tap="loadTask">刷新</button></view>
|
||||
<view class="section-heading"><text class="section-title">2. 托盘操作</text><button class="refresh-button" :disabled="loading" @tap="loadTask">{{ loading ? '刷新中…' : '刷新' }}</button></view>
|
||||
<view v-if="currentPallet" class="pallet-card">
|
||||
<view class="pallet-head"><text class="pallet-code">{{ currentPallet.palletNo }}</text><text class="pallet-status" :class="currentPallet.status === 'SEALED' ? 'sealed' : ''">{{ currentPallet.status === 'SEALED' ? '已封托' : '当前托盘' }}</text></view>
|
||||
<text class="pallet-meta">{{ currentPallet.cartonCount || 0 }} 箱 · {{ currentPallet.skuCount || 0 }} SKU · {{ currentPallet.weightKg || 0 }} kg · {{ currentPallet.volumeCbm || 0 }} m³</text>
|
||||
@@ -260,7 +259,7 @@
|
||||
.status, .pallet-status { flex-shrink: 0; padding: 4px 8px; border-radius: 99px; color: #155eef; font-size: 12px; background: #eff4ff; }.pallet-status.sealed { color: #067647; background: #ecfdf3; }
|
||||
.warehouse-summary { display: block; margin-top: 3px; color: #667085; font-size: 12px; }
|
||||
.compact-metrics { display: grid; grid-template-columns: repeat(5,1fr); margin-top: 8px; padding-top: 7px; border-top: 1px solid #edf1f5; }.compact-metrics > text { display: flex; align-items: center; justify-content: center; gap: 3px; color: #667085; font-size: 11px; white-space: nowrap; }.compact-metrics strong { color: #12233f; font-size: 15px; }.compact-metrics .pallet-readiness { color: #067647; }.compact-metrics .pallet-readiness.invalid,.compact-metrics .pallet-readiness.invalid strong { color: #b42318; }.pallet-setup-error { margin-top: 8px; margin-bottom: 0; text-align: left; }
|
||||
.section-title { display: block; color: #12233f; font-size: 18px; font-weight: 700; }.section-desc { display: block; margin: 2px 0 8px; color: #667085; font-size: 13px; line-height: 18px; }.section-heading > view { min-width: 0; }
|
||||
.section-title { display: block; color: #12233f; font-size: 18px; font-weight: 700; }.section-heading { align-items: center; }.refresh-button { display: flex; align-items: center; justify-content: center; flex-shrink: 0; box-sizing: border-box; min-width: 88px; height: 44px; margin: 0; padding: 0 16px; border: 1px solid #9dc0f4; border-radius: 8px; color: #155eef; font-size: 16px; font-weight: 700; line-height: normal; background: #eaf2ff; }.refresh-button::after { border: 0; }.refresh-button[disabled] { color: #718095; border-color: #dce5f0; background: #e8edf3; }
|
||||
.primary-button, .secondary-button { box-sizing: border-box; width: 100%; height: 46px; margin-top: 10px; border-radius: 9px; font-size: 14px; font-weight: 700; line-height: 44px; }.primary-button { border: 0; color: #fff; background: #1a73e8; }.secondary-button { border: 1px solid #8ab8ef; color: #155eef; background: #f6f9ff; }.primary-button[disabled],.secondary-button[disabled] { opacity: .45; }
|
||||
.unseal-button { border-color: #fda29b; color: #b42318; background: #fff5f4; }.pallet-hint.blocked { color: #b42318; }
|
||||
.unseal-dialog { box-sizing: border-box; width: min(350px, calc(100vw - 32px)); overflow: hidden; border-radius: 12px; background: #fff; }.unseal-copy { display: block; padding: 18px 16px; color: #475467; font-size: 14px; line-height: 21px; }.unseal-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 0 16px 16px; }.unseal-actions .secondary-button { margin-top: 0; }.danger-button { height: 46px; margin: 0; border: 0; border-radius: 9px; color: #fff; font-size: 14px; font-weight: 700; background: #d92d20; }.danger-button[disabled] { opacity: .45; }
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
</view>
|
||||
<view class="heading-row">
|
||||
<view><text class="heading">待入库任务</text><text class="summary">{{ loading ? '正在同步' : `共 ${tasks.length} 个任务` }}</text></view>
|
||||
<button class="refresh-button" :disabled="loading" @tap="refresh">刷新</button>
|
||||
</view>
|
||||
<view v-if="error" class="state error" role="alert">{{ error }}</view>
|
||||
<view v-else-if="!loading && !tasks.length" class="state">暂无待入库任务</view>
|
||||
@@ -44,7 +43,6 @@
|
||||
onShow() { if (!requireSession()) return; this.user = session.currentUser; this.loadTasks() },
|
||||
methods: {
|
||||
statusLabel(status) { return status === 'CLAIMED' ? '作业中' : '待领取' },
|
||||
refresh() { this.keyword = ''; this.loadTasks() },
|
||||
async loadTasks() {
|
||||
if (this.loading) return
|
||||
if (!this.user?.warehouseId) { this.error = '请返回首页选择作业仓库'; return }
|
||||
@@ -80,7 +78,6 @@
|
||||
.heading-row > view { display: flex; align-items: baseline; gap: 8px; }
|
||||
.heading { color: #12233f; font-size: 17px; font-weight: 700; }
|
||||
.summary { color: #667085; font-size: 11px; }
|
||||
.refresh-button { min-width: 64px; height: 40px; border: 0; border-radius: 6px; color: #155eef; font-size: 13px; line-height: 40px; background: #eaf2ff; }
|
||||
.state { padding: 24px 12px; border-radius: 10px; color: #667085; font-size: 13px; text-align: center; background: #fff; }
|
||||
.state.error { color: #b42318; background: #fff1f0; }
|
||||
.task-list { overflow: hidden; border: 1px solid #dce6f1; border-radius: 7px; background: #fff; }
|
||||
|
||||
+48
-66
@@ -129,7 +129,7 @@
|
||||
<text class="evidence-count" :class="{ complete: evidenceEntries(slot.type).length }">{{ evidenceEntries(slot.type).length ? `已拍 ${evidenceEntries(slot.type).length} 张` : '待拍摄' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<button class="evidence-btn evidence-add-btn" :disabled="evidenceReadOnly" @tap="chooseEvidence(slot)">{{ evidenceUploadLabel(slot.type) }}</button>
|
||||
<button class="evidence-btn evidence-add-btn" :disabled="evidenceReadOnly || evidenceUploading" @tap="chooseEvidence(slot)">{{ evidenceUploadLabel(slot.type) }}</button>
|
||||
</view>
|
||||
<view v-if="evidenceEntries(slot.type).length" class="evidence-photo-grid">
|
||||
<view v-for="photo in evidenceEntries(slot.type)" :key="photo.id || photo.fileId || photo.localPath" class="evidence-photo-item">
|
||||
@@ -143,18 +143,18 @@
|
||||
{{ evidenceUploadState(slot.type) }}
|
||||
</text>
|
||||
<text v-else-if="hasPendingLocalEvidence(slot.type)" class="evidence-upload-state pending">
|
||||
{{ slot.type === 'SEAL' ? '请填写封签号,保存后上传' : '照片待自动上传' }}
|
||||
{{ slot.type === 'SEAL' ? '请填写封签号,保存后上传' : '照片未保存,请重新拍照上传' }}
|
||||
</text>
|
||||
<button v-if="evidenceQueueEntry(slot.type)?.status === 'FAILED'" class="evidence-retry-btn" @tap="retryEvidence(slot.type)">重试上传</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="seal-row">
|
||||
<input v-model="sealNo" :disabled="evidenceReadOnly" class="seal-input" placeholder="输入封签号(必填)" maxlength="64" />
|
||||
<button class="evidence-btn seal-btn" :disabled="evidenceReadOnly || sealSaving || !sealReadyToSave" @tap="saveSealNo">{{ sealSaving ? '上传中…' : '保存并上传' }}</button>
|
||||
<button class="evidence-btn seal-btn" :disabled="evidenceReadOnly || evidenceUploading || sealSaving || !sealReadyToSave" @tap="saveSealNo">{{ sealSaving ? '上传中…' : '保存并上传' }}</button>
|
||||
</view>
|
||||
<view v-if="remoteError" class="remote-error-row"><text class="remote-error" role="alert">{{ remoteError }}</text><button class="evidence-retry-btn" :disabled="remoteLoading" @tap="refreshTask">刷新任务</button></view>
|
||||
<text v-if="evidenceReadOnly" class="version-hint" role="status">{{ loadingCompletionState.label }}</text>
|
||||
<button v-else class="loading-complete-btn" :disabled="submitting || !loadingStageReady || pickingVersion === null || !evidenceComplete" @tap="completeLoadingTask">确认装柜完成</button>
|
||||
<button v-else class="loading-complete-btn" :disabled="submitting || evidenceUploading || !loadingStageReady || pickingVersion === null || !evidenceComplete" @tap="completeLoadingTask">确认装柜完成</button>
|
||||
<button v-if="evidenceReadOnly && loadingCompletionState.phase !== 'COMPLETED'" class="evidence-retry-btn" :disabled="remoteLoading || submitting" @tap="refreshTask">刷新完成状态</button>
|
||||
<view v-if="pickingVersion === null" class="remote-error-row">
|
||||
<text class="version-hint" role="status">状态尚未同步,请刷新重试</text>
|
||||
<button class="evidence-retry-btn" :disabled="remoteLoading" @tap="refreshTask">刷新任务</button>
|
||||
@@ -340,12 +340,11 @@
|
||||
import { ITEM_STATUS, classifyScan, createItemStates, getPickSummary, isSealedPalletItem, submitStates, summarizeInventoryResources, remainingPhysicalCartons } from '@/utils/picking-state.js'
|
||||
import { SKIP_REASONS, INCOMPLETE_REASONS } from '@/data/demo-data.js'
|
||||
import { session, requireSession } from '@/stores/session.js'
|
||||
import { clearLoadingCompletionAttempt, clearPickingDraft, getPickingSession, restoreLoadingCompletionAttempt, restorePickingSession, saveLoadingCompletionAttempt, savePickingSession } from '@/stores/picking.js'
|
||||
import { clearPickingDraft, getPickingSession, restorePickingSession, savePickingSession } from '@/stores/picking.js'
|
||||
import { navigateBackOr } from '@/utils/navigation.js'
|
||||
import { startScanBroadcast } from '@/utils/scan-broadcast.js'
|
||||
import { playErrorSound, playSuccessSound } from '@/utils/audio-feedback.js'
|
||||
import { claimContainerPickingTask, completeContainerPickingTask, downloadEvidencePreview, EVIDENCE_SLOTS, getContainerPickingTask, getEvidence, getEvidencePreviewUrl, getPickingInventorySnapshot, isRemoteReady, listLoadingOrders, normalizePickingTask, partialContainerItem, pickContainerItem, pickContainerPallet, skipContainerItem, submitContainerPickingBatch, uploadEvidenceFile, voidEvidence } from '@/api/pda-loading.js'
|
||||
import { createEvidenceUploadQueue } from '@/utils/evidence-upload-queue.js'
|
||||
import { isOnline } from '@/utils/network.js'
|
||||
import { stableOperationId } from '@/utils/idempotency.js'
|
||||
import { stableTaskOperationIdentity } from '@/utils/task-identity.js'
|
||||
@@ -391,7 +390,7 @@
|
||||
selectedIncompleteReason: '',
|
||||
completionSummary: { picked: 0, partial: 0, skipped: 0, autoSkipped: 0 },
|
||||
evidenceSlots: EVIDENCE_SLOTS,
|
||||
evidenceFiles: {}, evidenceDrafts: {}, evidencePreviewCache: {}, evidenceQueueItems: [], evidenceQueue: null, evidenceContextId: 0, evidenceIdentity: null, cameraPicking: false, evidencePreviewOpening: false, evidencePreviewReturning: false, sealNo: '', sealSaving: false, pickingVersion: null, remotePick: null,
|
||||
evidenceFiles: {}, evidenceDrafts: {}, evidencePreviewCache: {}, evidenceQueueItems: [], evidenceUploading: false, evidenceContextId: 0, evidenceIdentity: null, cameraPicking: false, evidencePreviewOpening: false, evidencePreviewReturning: false, sealNo: '', sealSaving: false, pickingVersion: null, remotePick: null,
|
||||
remoteTaskId: null, assignmentVersion: null, submitId: '',
|
||||
taskRequestId: 0,
|
||||
remoteError: '', remoteLoading: false, submitting: false,
|
||||
@@ -837,10 +836,7 @@
|
||||
this.evidenceQueueItems = []
|
||||
this.sealNo = ''
|
||||
this.sealSaving = false
|
||||
this.evidenceQueue = createEvidenceUploadQueue({
|
||||
upload: (item, onProgress) => uploadEvidenceFile(item.taskId, item.warehouseId, item, item.localPath, onProgress),
|
||||
onChange: (items) => { if (this.evidenceContextId === contextId) this.evidenceQueueItems = items }
|
||||
})
|
||||
this.evidenceUploading = false
|
||||
},
|
||||
normalizeScanHistory(entries) {
|
||||
if (!Array.isArray(entries)) return []
|
||||
@@ -1254,7 +1250,6 @@
|
||||
if (seal?.sealNo) this.sealNo = seal.sealNo
|
||||
await this.loadEvidencePreviews(contextId, identity)
|
||||
if (!this.isEvidenceContextActive(contextId, identity)) return
|
||||
await this.flushPendingEvidence()
|
||||
} catch (error) {
|
||||
if (!this.isEvidenceContextActive(contextId, identity)) return
|
||||
this.remoteError = error.network ? '网络失败,装柜证据未加载,请刷新重试' : this.remoteFailureMessage(error, '装柜证据加载失败')
|
||||
@@ -1334,48 +1329,31 @@
|
||||
if (seal?.sealNo) this.sealNo = seal.sealNo
|
||||
this.removeDraftPhoto(type, localPath)
|
||||
},
|
||||
async queueEvidenceUpload(type, path, sealNo = null) {
|
||||
if (!this.evidenceIdentity?.taskId || !this.evidenceIdentity?.warehouseId || !isRemoteReady(this.evidenceIdentity.taskId)) { this.showToast('当前任务仓库尚未同步,证据保留本地', 'warning'); return }
|
||||
const contextId = this.evidenceContextId
|
||||
const identity = { ...this.evidenceIdentity }
|
||||
const queue = this.evidenceQueue
|
||||
const active = [...this.validEvidenceEntries(type)].reverse()[0]
|
||||
const expectedVersion = active?.version ?? 0
|
||||
const operationId = stableOperationId('evidence-upload', `${identity.taskId}|${identity.warehouseId}`, { evidenceType: type, expectedVersion, localPath: path, sealNo: sealNo || '' })
|
||||
const entry = queue.add({ taskId: identity.taskId, warehouseId: identity.warehouseId, evidenceType: type, expectedVersion, sealNo: sealNo || null, remark: null, operationId, localPath: path })
|
||||
this.debugSubmit('evidence.queue.start', { evidenceType: type, queueId: entry.id, evidenceIdentity: identity })
|
||||
await queue.flush()
|
||||
if (!this.isEvidenceContextActive(contextId, identity) || queue !== this.evidenceQueue) return
|
||||
const latest = queue.snapshot().find((item) => item.id === entry.id)
|
||||
this.debugSubmit('evidence.queue.result', { evidenceType: type, queueId: entry.id, status: latest?.status || 'missing', fileId: latest?.result?.fileId || null, error: latest?.error || '' })
|
||||
if (latest?.status !== 'SUCCEEDED') { this.remoteError = latest?.error || '文件上传失败'; return }
|
||||
this.applyEvidenceResponse(latest.result, type, path, identity)
|
||||
this.showToast(type === 'SEAL' ? '带锁码照上传成功,封签号已保存' : '照片已上传并保存', 'success')
|
||||
},
|
||||
async flushPendingEvidence() {
|
||||
if (!this.evidenceIdentity?.taskId || !this.evidenceIdentity?.warehouseId) return
|
||||
const pending = this.evidenceSlots.flatMap((slot) => this.evidenceEntries(slot.type).filter((entry) => !entry.id && entry.localPath).map((entry) => ({ type: slot.type, path: entry.localPath })))
|
||||
for (const item of pending) {
|
||||
if (!this.evidenceIdentity?.taskId || !this.evidenceIdentity?.warehouseId) return
|
||||
if (item.type === 'SEAL' && !String(this.sealNo || '').trim()) continue
|
||||
await this.queueEvidenceUpload(item.type, item.path, item.type === 'SEAL' ? this.sealNo : null)
|
||||
}
|
||||
},
|
||||
async retryEvidence(type) {
|
||||
if (!this.requireEvidenceCapture()) return
|
||||
const item = this.evidenceQueueEntry(type)
|
||||
const contextId = this.evidenceContextId
|
||||
const identity = { ...this.evidenceIdentity }
|
||||
const queue = this.evidenceQueue
|
||||
if (!item || !queue.retry(item.id)) return
|
||||
this.remoteError = ''
|
||||
await queue.flush()
|
||||
if (!this.isEvidenceContextActive(contextId, identity) || queue !== this.evidenceQueue) return
|
||||
const latest = queue.latest(type)
|
||||
if (latest?.status !== 'SUCCEEDED') { this.remoteError = latest?.error || '文件上传失败'; return }
|
||||
this.applyEvidenceResponse(latest.result, type, item.localPath, identity)
|
||||
this.showToast(type === 'SEAL' ? '带锁码照上传成功,封签号已保存' : '照片重试上传成功', 'success')
|
||||
},
|
||||
async queueEvidenceUpload(type, path, sealNo = null) {
|
||||
if (this.evidenceUploading || this.evidenceReadOnly) return
|
||||
if (!this.evidenceIdentity?.taskId || !this.evidenceIdentity?.warehouseId || !isRemoteReady(this.evidenceIdentity.taskId)) { this.showToast('当前任务仓库尚未同步,请刷新后重新操作', 'warning'); return }
|
||||
const contextId = this.evidenceContextId
|
||||
const identity = { ...this.evidenceIdentity }
|
||||
const current = [...this.validEvidenceEntries(type)].reverse()[0]
|
||||
const entry = { id: `${Date.now()}-${Math.random()}`, evidenceType: type, status: 'UPLOADING', progress: 0, error: '' }
|
||||
this.evidenceQueueItems = [...this.evidenceQueueItems.filter(item => item.evidenceType !== type), entry]
|
||||
this.evidenceUploading = true
|
||||
this.remoteError = ''
|
||||
try {
|
||||
const result = await uploadEvidenceFile(identity.taskId, identity.warehouseId, {
|
||||
evidenceType: type, expectedVersion: current?.version ?? 0, sealNo,
|
||||
operationId: `evidence-${Date.now()}-${Math.random().toString(36).slice(2)}`
|
||||
}, path, progress => { if (this.isEvidenceContextActive(contextId, identity)) entry.progress = progress })
|
||||
if (!this.isEvidenceContextActive(contextId, identity)) return
|
||||
entry.status = 'SUCCEEDED'
|
||||
this.applyEvidenceResponse(result, type, path, identity)
|
||||
this.showToast(type === 'SEAL' ? '带锁码照上传成功,封签号已保存' : '照片已上传并保存', 'success')
|
||||
} catch (error) {
|
||||
if (!this.isEvidenceContextActive(contextId, identity)) return
|
||||
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 })) } }
|
||||
},
|
||||
async saveSealNo() {
|
||||
if (this.sealSaving) return
|
||||
if (!String(this.sealNo || '').trim()) { this.showToast('请输入封签号', 'warning'); return }
|
||||
@@ -1411,18 +1389,18 @@
|
||||
}
|
||||
},
|
||||
async completeLoadingTask() {
|
||||
if (!this.requireEvidenceStage()) return
|
||||
if (this.evidenceUploading || !this.requireEvidenceStage()) return
|
||||
if (!this.evidenceIdentity?.taskId || !this.evidenceIdentity?.warehouseId || !isRemoteReady(this.evidenceIdentity.taskId)) { this.showToast('装柜任务或仓库尚未同步,请刷新后重试', 'warning'); return }
|
||||
if (this.pickingVersion === null) { this.showToast(VERSION_SYNC_MESSAGE, 'warning'); return }
|
||||
if (!this.evidenceComplete) { this.showToast('五类有效照片和封签号均为必填', 'warning'); return }
|
||||
const contextId = this.evidenceContextId
|
||||
const identity = { ...this.evidenceIdentity }
|
||||
const serverAttempt = this.remotePick?.completionCommand
|
||||
const savedAttempt = restoreLoadingCompletionAttempt(this.draftIdentity()) || (serverAttempt?.operationId ? {
|
||||
const savedAttempt = serverAttempt?.status === 'FAILED' && serverAttempt.operationId ? {
|
||||
operationId: serverAttempt.operationId,
|
||||
expectedTaskVersion: serverAttempt.expectedTaskVersion,
|
||||
remark: serverAttempt.remark || 'PDA确认装柜完成'
|
||||
} : null)
|
||||
} : null
|
||||
const expectedTaskVersion = savedAttempt?.expectedTaskVersion ?? Number(this.pickingVersion)
|
||||
const completionIdentity = this.draftIdentity()
|
||||
const operationIdentity = stableTaskOperationIdentity(completionIdentity)
|
||||
@@ -1433,8 +1411,10 @@
|
||||
containerBookingId: completionIdentity.containerBookingId
|
||||
})
|
||||
const completionAttempt = { operationId, expectedTaskVersion, remark: savedAttempt?.remark || 'PDA确认装柜完成' }
|
||||
saveLoadingCompletionAttempt(this.draftIdentity(), completionAttempt)
|
||||
const submission = {}
|
||||
this._submissionOwner = submission
|
||||
this.submitting = true
|
||||
this.remoteError = ''
|
||||
const started = Date.now()
|
||||
let accepted = false
|
||||
try {
|
||||
@@ -1479,11 +1459,10 @@
|
||||
return
|
||||
}
|
||||
if (phase !== COMPLETION_PHASE.COMPLETED) {
|
||||
this.remoteError = phase === COMPLETION_PHASE.FAILED ? '装柜完成失败,可使用原操作重试完成' : '提交结果待确认,请刷新任务'
|
||||
this.remoteError = phase === COMPLETION_PHASE.FAILED ? '装柜完成失败,请重新操作' : '提交结果待确认,请刷新任务'
|
||||
this.showToast(phase === COMPLETION_PHASE.FAILED ? '装柜完成失败' : '提交结果待确认', 'warning')
|
||||
return
|
||||
}
|
||||
clearLoadingCompletionAttempt(this.draftIdentity())
|
||||
this.remoteError = ''
|
||||
this.showToast('装柜已完成', 'success')
|
||||
} catch (error) {
|
||||
@@ -1495,9 +1474,8 @@
|
||||
return
|
||||
}
|
||||
if (shouldReconcileCompletion(error)) {
|
||||
this.remoteError = '提交结果待确认,请返回任务列表刷新'
|
||||
this.remoteError = '提交结果待确认,请刷新任务后重新操作'
|
||||
this.showToast('提交结果待确认', 'warning')
|
||||
navigateBackOr('/pages/tasks/tasks')
|
||||
return
|
||||
}
|
||||
if (this.isTaskConflict(error)) {
|
||||
@@ -1509,7 +1487,7 @@
|
||||
this.showToast('装柜完成失败', 'error')
|
||||
}
|
||||
finally {
|
||||
if (this.isEvidenceContextActive(contextId, identity)) this.submitting = false
|
||||
if (this._submissionOwner === submission) { this.submitting = false; this._submissionOwner = null }
|
||||
}
|
||||
},
|
||||
async pickScannedBox(item, boxCode) {
|
||||
@@ -1635,6 +1613,8 @@
|
||||
itemId, itemVersion: item.version, taskVersion: this.pickingVersion, ...payload
|
||||
})
|
||||
const common = { warehouseId: this.currentBox.warehouseId, version: Number(item.version || 0), operationId }
|
||||
const submission = {}
|
||||
this._submissionOwner = submission
|
||||
this.submitting = true
|
||||
this.remoteError = ''
|
||||
try {
|
||||
@@ -1653,7 +1633,7 @@
|
||||
}
|
||||
return false
|
||||
} finally {
|
||||
this.submitting = false
|
||||
if (this._submissionOwner === submission) { this.submitting = false; this._submissionOwner = null }
|
||||
}
|
||||
},
|
||||
applyImmediateTaskResult(result) {
|
||||
@@ -1747,6 +1727,8 @@
|
||||
return
|
||||
}
|
||||
if (remoteRequired) {
|
||||
const submission = {}
|
||||
this._submissionOwner = submission
|
||||
this.submitting = true
|
||||
try {
|
||||
if (!this.remoteTaskId) throw new Error('尚未进入服务端拣货任务,请联网刷新后重试')
|
||||
@@ -1802,7 +1784,7 @@
|
||||
this.remoteError = error.network ? '网络失败,拣货完成未提交,请重试' : this.remoteFailureMessage(error, '拣货完成失败')
|
||||
this.showToast('拣货完成未提交,请查看错误提示', 'error')
|
||||
return
|
||||
} finally { this.submitting = false }
|
||||
} finally { if (this._submissionOwner === submission) { this.submitting = false; this._submissionOwner = null } }
|
||||
}
|
||||
const result = submitStates(this.currentBox.items, this.itemStates)
|
||||
this.itemStates = result.states
|
||||
|
||||
Reference in New Issue
Block a user