diff --git a/src/pages/relabel/relabel.vue b/src/pages/relabel/relabel.vue
index b2dc304..8c6f3bd 100644
--- a/src/pages/relabel/relabel.vue
+++ b/src/pages/relabel/relabel.vue
@@ -28,7 +28,7 @@
{{ group.skuCode }}FBA 目的仓:{{ group.destinationFbaWarehouseCode || '—' }}剩余 {{ group.remaining }} 件
{{ group.expectedPackages }}贴标预报{{ group.relabelledPackages }}已贴
- 来源托盘{{ isReturnBulk ? '换标数量' : '拆箱数量' }}{{ source.palletCode || '未记录托盘' }}{{ isReturnBulk ? '换标' : '拆箱' }} {{ source.expectedPackages }} 件合计{{ isReturnBulk ? '换标' : '拆箱' }}{{ group.expectedPackages }} 件
+ 来源托盘换标数量来源托盘拆箱数量{{ source.palletCode || '未记录托盘' }}{{ isReturnBulk ? '换标' : '拆箱' }} {{ source.expectedPackages }} 件合计{{ isReturnBulk ? '换标' : '拆箱' }}{{ group.expectedPackages }} 件
diff --git a/src/pages/warehouse-transfer/warehouse-transfer.vue b/src/pages/warehouse-transfer/warehouse-transfer.vue
index f8afaad..271b3a7 100644
--- a/src/pages/warehouse-transfer/warehouse-transfer.vue
+++ b/src/pages/warehouse-transfer/warehouse-transfer.vue
@@ -23,8 +23,9 @@
正在读取转运明细请稍候,不要重复选择
作业详情进入后完成当前转运单的测量、打托和拍照
- 库存转运 · 无需测量该单来源于仓库现有库存,不需要重复测量或上传现场照片。请进入托盘作业,按来源托盘执行整托转运、拆托重打,或与相同目的仓合托。
-
+ 测量已完成该转运单已完成 PDA 测量,不再重复进入测量或托盘作业。
+ 库存转运 · 无需测量该单来源于仓库现有库存,不需要重复测量或上传现场照片。请进入托盘作业,按来源托盘执行整托转运、拆托重打,或与相同目的仓合托。
+
当前测量任务{{ selected.transferNo }}
{{ totalCartons }}实收箱
@@ -94,8 +95,8 @@ const newPallet = () => ({ key: `${Date.now()}-${Math.random()}`, cartonCount: 0
const restoredPallet = (value, index) => ({
key: `server-${value.draftId || value.id || index}`,
cartonCount: Number(value.cartonCount || 0), lengthCm: value.lengthCm, widthCm: value.widthCm, heightCm: value.heightCm, grossWeightKg: value.grossWeightKg,
- generated: Boolean(value.palletNo), bound: Boolean(value.boundAt || value.status === 'BOUND'), collapsed: Boolean(value.boundAt || value.status === 'BOUND'),
- palletNo: String(value.palletNo || ''), fbaWarehouseCode: String(value.fbaWarehouseCode || ''), labelDownloadPath: String(value.labelDownloadPath || ''), bindCode: '', busy: false,
+ generated: Boolean(value.palletNo), bound: Boolean(value.boundAt || value.status === 'BOUND'), collapsed: Boolean(value.boundAt || value.status === 'BOUND'),
+ palletNo: String(value.palletNo || ''), fbaWarehouseCode: String(value.fbaWarehouseCode || ''), labelDownloadPath: String(value.labelDownloadPath || ''), bindCode: String(value.palletNo || ''), busy: false,
draftId: value.draftId || value.id, version: value.version
})
@@ -106,7 +107,8 @@ export default {
completedDestinationLabel() { return this.destinationLabel({ fbaWarehouseCode: this.completedDestination, destinationType: this.completedDestinationType }) },
totalCartons() { return this.pallets.reduce((sum, pallet) => sum + Math.max(0, Number(pallet.cartonCount) || 0), 0) },
cartonDifference() { return this.totalCartons - Number(this.selected?.packageCount || 0) },
- isInventoryTransfer() { return Boolean(this.selected && this.selected.inboundCode && this.selected.inboundCode !== this.selected.transferNo) },
+ isInventoryTransfer() { return Boolean(this.selected && this.selected.status === 'WAIT_PDA_RECEIVING' && this.selected.inboundCode && this.selected.inboundCode !== this.selected.transferNo) },
+ isMeasurementComplete() { return Boolean(this.selected && !['WAIT_PDA_RECEIVING', 'PARTIALLY_RECEIVED'].includes(String(this.selected.status))) },
totalVolume() { return this.pallets.reduce((sum, pallet) => sum + this.rawPalletVolume(pallet), 0).toFixed(3) },
totalWeight() { return this.pallets.reduce((sum, pallet) => sum + Math.max(0, Number(pallet.grossWeightKg) || 0), 0).toFixed(2) },
validationMessage() {
@@ -126,7 +128,7 @@ export default {
watch: {
pallets: { deep: true, handler() { if (!this.submitting) this.pendingKey = '' } }
},
- onShow() { if (requireSession()) { this.user = session.currentUser; restoreWarehouseWork(`${this.user.id}:${this.user.warehouseId}`); this.startScanner(); this.loadCandidates().then(() => { const activeNo = String(warehouseWork.warehouseTransfer.currentNo || ''); const taskNo = this.pendingTaskNo || activeNo; if (this.entryMode === 'work' && taskNo) { const active = this.candidates.find((item) => String(item.transferNo) === taskNo); if (active) { this.pendingTaskNo = ''; void this.select(active) } } }) } },
+ onShow() { if (requireSession()) { this.user = session.currentUser; restoreWarehouseWork(`${this.user.id}:${this.user.warehouseId}`); this.startScanner(); this.loadCandidates().then(() => { const activeNo = String(warehouseWork.warehouseTransfer.currentNo || ''); const taskNo = this.pendingTaskNo || activeNo; if (this.entryMode === 'work' && taskNo) { const active = this.candidates.find((item) => String(item.transferNo) === taskNo); if (active) { const fromExplicitTask = Boolean(this.pendingTaskNo); this.pendingTaskNo = ''; void this.select(active, fromExplicitTask) } } }) } },
onLoad(options) { this.entryMode = options?.mode === 'list' ? 'list' : 'work'; this.pendingTaskNo = String(options?.task || '') },
onHide() { this.stopScanner() },
beforeUnmount() { this.stopScanner() },
@@ -163,12 +165,28 @@ export default {
catch (error) { this.error = error; pallet.busy = false }
},
async printDraftPallet(pallet) { if (!pallet.labelDownloadPath) { this.error = new Error('服务端未返回托盘标签下载地址'); return }; await this.openLabelPdf(() => downloadWarehouseTransferPalletLabel(pallet.labelDownloadPath)) },
- async loadCandidates() { this.loading = true; this.error = null; try { const activeNo = String(warehouseWork.warehouseTransfer.currentNo || ''); this.candidates = (await listWarehouseTransferCandidates()).map((item) => String(item.transferNo) === activeNo && item.status === 'WAIT_PDA_RECEIVING' ? { ...item, status: 'PARTIALLY_RECEIVED' } : item) } catch (e) { this.error = e } finally { this.loading = false } },
- async select(item) {
+ async loadCandidates() {
+ this.loading = true; this.error = null
+ try {
+ const activeNo = String(warehouseWork.warehouseTransfer.currentNo || '')
+ const measuredStatuses = new Set(['WAIT_PDA_RECEIVING', 'PARTIALLY_RECEIVED'])
+ this.candidates = (await listWarehouseTransferCandidates()).map((item) => String(item.transferNo) === activeNo && item.status === 'WAIT_PDA_RECEIVING' ? { ...item, status: 'PARTIALLY_RECEIVED' } : item)
+ this.candidates = this.candidates.filter((item) => measuredStatuses.has(String(item.status)))
+ // 服务端已完成当前单但设备在提交响应前断网时,本地 currentNo 会遗留。
+ // 候选已成功读取且当前单不再可测,清掉本地锁,允许继续下一票。
+ if (activeNo && !this.candidates.some((item) => String(item.transferNo) === activeNo && measuredStatuses.has(String(item.status)))) {
+ resetWarehouseDomain('warehouseTransfer')
+ }
+ if (this.selected && !this.candidates.some((item) => String(item.transferNo) === String(this.selected.transferNo))) {
+ this.selected = null; this.pallets = [newPallet()]; this.photoFileIds = []; this.photoUrls = {}; this.photoNames = []
+ }
+ } catch (e) { this.error = e } finally { this.loading = false }
+ },
+ async select(item, fromExplicitTask = false) {
if (this.detailLoading || this.submitting) return
const requestedNo = String(item?.transferNo || '')
const activeNo = String(warehouseWork.warehouseTransfer.currentNo || '')
- if (!activeNo) {
+ if (!activeNo && !fromExplicitTask) {
const result = await new Promise((resolve) => uni.showModal({ title: '开始测量', content: `确认开始测量转运单 ${requestedNo} 吗?开始后本设备需先完成该单,才能选择下一单。`, confirmText: '确认开始', cancelText: '取消', success: resolve, fail: () => resolve({ confirm: false }) }))
if (!result.confirm) return
}