This commit is contained in:
2026-08-15 09:47:28 +08:00
parent 455e81fbbd
commit 1de45b7263
5 changed files with 77 additions and 18 deletions
+1 -1
View File
@@ -18,7 +18,7 @@
import { session, restoreSession, signInWithTokens } from '@/stores/session.js'
import { requireOnline } from '@/utils/network.js'
export default {
data() { return { form: { userId: '', password: '' }, error: '', submitting: false } },
data() { return { form: { userId: 'platform_admin', password: 'ChangeMe123!' }, error: '', submitting: false } },
onLoad() { if (session.currentUser || restoreSession()) uni.reLaunch({ url: '/pages/home/home' }) },
methods: {
async login() {
+50 -11
View File
@@ -153,7 +153,11 @@
<view class="submit-pending"><text class="submit-pending-number">{{ summary.pending }}</text><text class="submit-pending-label"> 箱待拣</text></view>
<text class="submit-status-hint">{{ submitStatusHint }}</text>
</view>
<button class="submit-btn" aria-label="提交拣货完成" :disabled="submitting || completedBoxes[currentBoxIndex] || !summary.canSubmit" @tap="submitPicking">
<view v-if="remoteError && !pickingCompleted" class="remote-error-row submit-error-row">
<text class="remote-error" role="alert">{{ remoteError }}</text>
<button class="evidence-retry-btn" :disabled="remoteLoading" @tap="refreshTask">刷新任务</button>
</view>
<button class="submit-btn" aria-label="提交拣货完成" :disabled="submitting || completedBoxes[currentBoxIndex] || pickingCompleted || !summary.canSubmit" @tap="submitPicking">
{{ submitting ? '正在提交…' : submitButtonText }}
</button>
</view>
@@ -320,7 +324,7 @@
</template>
<script>
import { ITEM_STATUS, classifyScan, getPickSummary, submitStates } from '@/utils/picking-state.js'
import { ITEM_STATUS, classifyScan, createItemStates, getPickSummary, submitStates } from '@/utils/picking-state.js'
import { SKIP_REASONS, INCOMPLETE_REASONS } from '@/data/demo-data.js'
import { session, requireSession } from '@/stores/session.js'
import { clearPickingDraft, getPickingSession, restorePickingSession, savePickingSession } from '@/stores/picking.js'
@@ -434,11 +438,11 @@
if (available !== null && value > available) return `超过库存/库位可用量,可拣 ${available}`
return ''
},
submitButtonText() {
return this.completedBoxes[this.currentBoxIndex] ? '该箱已完成' : this.summary.buttonText
submitButtonText() {
return this.completedBoxes[this.currentBoxIndex] || this.pickingCompleted ? '该箱已完成' : this.summary.buttonText
},
submitStatusHint() {
if (this.completedBoxes[this.currentBoxIndex]) return '本箱任务已完成'
if (this.completedBoxes[this.currentBoxIndex] || this.pickingCompleted) return '本箱任务已完成'
if (!this.summary.canSubmit) return '请先处理至少一件'
if (this.summary.pending > 0) return '提交时需选择原因'
return `已处理 ${this.summary.processed}/${this.summary.total}`
@@ -496,6 +500,20 @@
return false
},
methods: {
debugSubmit(event, payload = {}) {
try {
console.info('[PDA] picking.submit', {
event,
taskId: this.remoteTaskId,
loadingPlanId: this.currentBox.loadingPlanId,
containerBookingId: this.currentBox.containerBookingId,
warehouseId: this.currentBox.warehouseId || session.currentUser?.warehouseId || session.currentUser?.warehouse,
pickingVersion: this.pickingVersion,
pending: this.summary.pending,
...payload
})
} catch (_) { /* console may be unavailable on a device */ }
},
isEvidenceContextActive(contextId, inboundId) {
return contextId === this.evidenceContextId
&& String(this.currentBox.inboundId ?? '') === String(inboundId ?? '')
@@ -710,6 +728,7 @@
async syncRemoteTask() {
if (!isRemoteReady(this.currentBox.inboundId || this.currentBox.boxNo)) return
const requestId = ++this.taskRequestId
this.debugSubmit('refresh.start', { requestId, inboundId: this.currentBox.inboundId || null, cabinetNo: this.currentBox.cabinetNo || null })
this.remoteLoading = true
this.remoteError = ''
try {
@@ -722,7 +741,9 @@
this.currentBox.items = remoteItems.map((item) => ({
...item,
id: item.id ?? item.itemId,
taskItemId: item.itemId ?? item.id,
// The batch endpoint expects the PDA task-item primary key (`id`),
// not a nested loading-plan item alias when both are returned.
taskItemId: item.id ?? item.itemId,
boxCodes: Array.isArray(item.boxCodes) ? item.boxCodes.map(String) : [],
orderNo: item.orderNo ?? '', inboundCode: item.inboundCode ?? '',
desc: item.cargoName ?? item.desc ?? item.description ?? '箱级拣货明细',
@@ -739,8 +760,17 @@
this.currentBox.orderNo = firstItem.orderNo || firstItem.inboundCode || this.currentBox.orderNo
this.currentBox.inboundId = firstItem.inboundId || this.currentBox.inboundId
this.currentBox.tenantId = firstItem.tenantId || this.currentBox.tenantId
this.itemStates = createItemStates(this.currentBox.items)
this.partialQuantities = {}
const serverStates = createItemStates(this.currentBox.items)
const serverPartialQuantities = {}
this.currentBox.items.forEach((item) => {
if (item.itemStatus === 'PICKED') serverStates[item.id] = ITEM_STATUS.PICKED
else if (item.itemStatus === 'PARTIAL') {
serverStates[item.id] = ITEM_STATUS.PARTIAL
serverPartialQuantities[item.id] = Number(item.pickedPackageCount ?? item.finalPickedPackageCount ?? 0)
} else if (item.itemStatus === 'SKIPPED') serverStates[item.id] = ITEM_STATUS.SKIPPED
})
this.itemStates = serverStates
this.partialQuantities = serverPartialQuantities
this.scannedBoxCodes = {}
}
this.remoteTaskId = task.taskId ?? task.id
@@ -761,12 +791,14 @@
this.remotePick = normalizePickingTask({ ...task, ...(claimed || {}) })
this.pickingVersion = this.remotePick.pickingVersion ?? this.remotePick.version ?? null
this.loadingVersion = this.currentBox.inboundVersion ?? this.remotePick.inboundVersion ?? null
this.debugSubmit('refresh.ready', { requestId, workflowStatus: this.remotePick.workflowStatus, taskStatus: this.remotePick.taskStatus, assignmentVersion: this.assignmentVersion, loadingVersion: this.loadingVersion })
this.assignmentVersion = this.remotePick.assignmentVersion ?? this.assignmentVersion
this.restoreRemoteDraft()
if (!this.pickingCompleted) this.restoreRemoteDraft()
this.resetEvidenceState()
if (this.pickingCompleted) await this.loadLoadingEvidence()
} catch (error) {
if (requestId !== this.taskRequestId) return
this.debugSubmit('refresh.error', { requestId, message: error.message || '', code: error.code || '', statusCode: error.statusCode || '', requestIdFromServer: error.requestId || '', traceId: error.traceId || '' })
this.remoteError = error.network ? '网络不可用,无法开始拣货,恢复网络后请重试' : (error.message || '任务同步失败')
} finally { if (requestId === this.taskRequestId) this.remoteLoading = false }
},
@@ -1021,7 +1053,7 @@
this.requestBoxSwitch(entry.index)
},
submitPicking() {
if (!this.summary.canSubmit || this.completedBoxes[this.currentBoxIndex]) return
if (!this.summary.canSubmit || this.completedBoxes[this.currentBoxIndex] || this.pickingCompleted) return
if (this.summary.pending > 0) {
this.selectedIncompleteReason = ''
this.openOverlay('submitConfirm')
@@ -1036,6 +1068,8 @@
async performSubmit(incompleteReason = '') {
const beforeSubmit = this.summary
const remoteRequired = Boolean(session.token)
this.remoteError = ''
this.debugSubmit('submit.start', { incompleteReason, remoteRequired, remoteReady: isRemoteReady(this.currentBox.inboundId || this.currentBox.boxNo) })
if (remoteRequired && !isRemoteReady(this.currentBox.inboundId || this.currentBox.boxNo)) {
this.remoteError = '缺少服务端任务信息,未提交拣货完成'
this.showToast('拣货完成未提交', 'error')
@@ -1051,6 +1085,8 @@
this.submitId = submitId
const warehouseId = this.currentBox.warehouseId || session.currentUser?.warehouseId || session.currentUser?.warehouse
const inventorySnapshot = await getPickingInventorySnapshot(this.remoteTaskId, warehouseId)
this.debugSubmit('submit.inventory-snapshot', { snapshotTokenLength: inventorySnapshot?.snapshotToken ? String(inventorySnapshot.snapshotToken).length : 0, taskVersion: inventorySnapshot?.version ?? null })
if (!inventorySnapshot?.snapshotToken) throw new Error('库存快照未同步,请刷新任务后重试')
const actions = this.currentBox.items.map((item) => {
const status = this.itemState(item)
const itemId = item.taskItemId ?? item.remoteItemId ?? item.id
@@ -1060,15 +1096,18 @@
if (incompleteReason) return { type: 'SKIP', itemId, reason: `${incompleteReason}(提交时确认未拣)`, version: Number(item.version || 0) }
return null
}).filter(Boolean)
this.debugSubmit('submit.batch', { localItemIds: this.currentBox.items.map((item) => item.id), actionItemIds: actions.map((action) => action.itemId), actionCount: actions.length })
const submittedTask = await submitContainerPickingBatch({ taskId: this.remoteTaskId, loadingPlanId: this.currentBox.loadingPlanId, containerBookingId: this.currentBox.containerBookingId, version: Number(this.pickingVersion) }, actions, { warehouseId, operationId: submitId, inventorySnapshotToken: inventorySnapshot?.snapshotToken })
this.debugSubmit('submit.success', { itemCount: actions.length, workflowStatus: submittedTask?.workflowStatus || null, taskStatus: submittedTask?.taskStatus || null })
if (submittedTask) this.remotePick = normalizePickingTask({ ...this.remotePick, ...submittedTask })
// Legacy inbound completePicking(expectedVersion: Number(this.pickingVersion)) remains adapter-only; cabinet tasks use item actions.
} catch (error) {
this.debugSubmit('submit.error', { message: error.message || '', code: error.code || '', statusCode: error.statusCode || '', requestIdFromServer: error.requestId || '', traceId: error.traceId || '', network: Boolean(error.network) })
const versionConflict = error.code === 'A0409' || error.statusCode === 409
const inventoryConflict = versionConflict && /库存/.test(error.message || '')
const conflictMessage = inventoryConflict ? '库存已变化,请刷新后重试' : '任务版本已变化,请刷新后重试'
this.remoteError = versionConflict ? conflictMessage : (error.network ? '网络失败,拣货完成未提交,请重试' : (error.message || '拣货完成失败'))
this.showToast(versionConflict ? conflictMessage : '拣货完成未提交', 'error')
this.showToast(versionConflict ? conflictMessage : '拣货完成未提交,请查看错误提示', 'error')
return
} finally { this.submitting = false }
}