提交
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
<view class="candidate-list">
|
||||
<button v-for="item in candidates" :key="item.transferNo" class="transfer-card" :class="{ selected: selected?.transferNo === item.transferNo }" @tap="select(item)">
|
||||
<view class="transfer-card-head"><text class="transfer-no">{{ item.transferNo }}</text><text class="status-pill">{{ statusLabel(item.status) }}</text></view>
|
||||
<view class="task-metrics"><view><text>计划箱数</text><strong>{{ item.packageCount || 0 }}</strong></view><view><text>FBA 目的仓</text><strong>{{ item.fbaWarehouseCode || '暂未确定' }}</strong></view><view><text>换标</text><strong>{{ item.needRelabel ? '需要' : '不需要' }}</strong></view></view>
|
||||
<view class="task-metrics"><view><text>计划箱数</text><strong>{{ item.packageCount || 0 }}</strong></view><view><text>{{ item.destinationType === 'PRIVATE' ? '目的仓' : 'FBA 目的仓' }}</text><strong>{{ destinationLabel(item) }}</strong></view><view><text>换标</text><strong>{{ item.needRelabel ? '需要' : '不需要' }}</strong></view></view>
|
||||
<text class="transfer-meta">入仓码 {{ item.inboundCode || '—' }}</text>
|
||||
</button>
|
||||
</view>
|
||||
@@ -45,7 +45,7 @@
|
||||
<label><text class="field-label">当前托箱数</text><view class="input-with-unit important"><input type="number" v-model.number="pallet.cartonCount" :disabled="pallet.generated" placeholder="箱数" /><text>箱</text></view></label>
|
||||
</view>
|
||||
<button v-if="!pallet.generated" class="generate-button" :disabled="!palletReady(pallet) || pallet.busy" @tap="generatePallet(pallet)">{{ pallet.busy ? '生成中…' : '生成托盘号' }}</button>
|
||||
<view v-else class="generated-card"><view><text class="print-code">{{ pallet.palletNo }}</text><text>{{ pallet.fbaWarehouseCode || selected.fbaWarehouseCode || '目的仓待定' }}</text></view><button :disabled="pallet.busy" @tap="printDraftPallet(pallet)">打印标签</button></view>
|
||||
<view v-else class="generated-card"><view><text class="print-code">{{ pallet.palletNo }}</text><text>{{ destinationLabel(pallet, selected) }}</text></view><button :disabled="pallet.busy" @tap="printDraftPallet(pallet)">打印标签</button></view>
|
||||
<view v-if="pallet.generated && !pallet.bound" class="bind-panel"><ScanTargetInput :name="`transfer-pallet-${index}`" v-model="pallet.bindCode" label="确认实物托盘码" placeholder="扫描或手输新托盘标签号" :active="activePalletKey === pallet.key" @activate="activePalletKey = pallet.key" @submit="bindPallet(pallet)" /><button :disabled="pallet.busy || !String(pallet.bindCode || '').trim()" @tap="bindPallet(pallet)">{{ pallet.busy ? '确认中…' : '确认绑定' }}</button></view>
|
||||
<view v-if="pallet.bound" class="bound-state">已绑定实物托盘 {{ pallet.palletNo }}</view>
|
||||
</view>
|
||||
@@ -67,8 +67,8 @@
|
||||
<view v-if="error" class="transfer-error" role="alert"><text class="feedback-title">操作失败</text><text>{{ error.message || error }}</text><text v-if="error.requestId">requestId:{{ error.requestId }}</text></view>
|
||||
<view v-if="success" class="transfer-success" role="status"><text class="feedback-title">提交成功</text><text>测量与托盘打托已完成</text></view>
|
||||
<view v-if="completedPallets.length" class="print-card">
|
||||
<view class="photo-head"><view><text class="measure-title">新托盘标签</text><text class="measure-hint">{{ completedDestination ? `FBA 目的仓 ${completedDestination}` : '目的仓待定' }} · 逐托打开 PDF 后打印并粘贴</text></view></view>
|
||||
<view v-for="pallet in completedPallets" :key="pallet.palletNo" class="print-row"><view><text class="print-code">{{ pallet.palletNo }}</text><text>{{ pallet.cartonCount }} 箱 · {{ pallet.fbaWarehouseCode || completedDestination || '目的仓待定' }}</text></view><button @tap="printPallet(pallet)">打印标签</button></view>
|
||||
<view class="photo-head"><view><text class="measure-title">新托盘标签</text><text class="measure-hint">{{ completedDestinationLabel }} · 逐托打开 PDF 后打印并粘贴</text></view></view>
|
||||
<view v-for="pallet in completedPallets" :key="pallet.palletNo" class="print-row"><view><text class="print-code">{{ pallet.palletNo }}</text><text>{{ pallet.cartonCount }} 箱 · {{ destinationLabel(pallet, { destinationType: completedDestinationType }) }}</text></view><button @tap="printPallet(pallet)">打印标签</button></view>
|
||||
</view>
|
||||
</view></scroll-view>
|
||||
</view>
|
||||
@@ -93,8 +93,9 @@ const restoredPallet = (value, index) => ({
|
||||
|
||||
export default {
|
||||
components: { PortalHeader, ScanTargetInput },
|
||||
data() { return { user: session.currentUser, candidates: [], selected: null, pallets: [newPallet()], activePalletKey: '', photoFileIds: [], photoUrls: {}, photoNames: [], completedPallets: [], completedTransferNo: '', completedDestination: '', loading: false, detailLoading: false, submitting: false, uploadingPhoto: false, openingLabel: false, error: null, success: false, pendingKey: '' } },
|
||||
data() { return { user: session.currentUser, candidates: [], selected: null, pallets: [newPallet()], activePalletKey: '', photoFileIds: [], photoUrls: {}, photoNames: [], completedPallets: [], completedTransferNo: '', completedDestination: '', completedDestinationType: '', loading: false, detailLoading: false, submitting: false, uploadingPhoto: false, openingLabel: false, error: null, success: false, pendingKey: '' } },
|
||||
computed: {
|
||||
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) },
|
||||
totalVolume() { return this.pallets.reduce((sum, pallet) => sum + this.rawPalletVolume(pallet), 0).toFixed(3) },
|
||||
@@ -119,6 +120,7 @@ export default {
|
||||
onHide() { this.stopScanner() },
|
||||
beforeUnmount() { this.stopScanner() },
|
||||
methods: {
|
||||
destinationLabel(value, fallback = {}) { const code = String(value?.fbaWarehouseCode || fallback?.fbaWarehouseCode || '').trim(); if (code) return code; const type = value?.destinationType || fallback?.destinationType; return type === 'PRIVATE' ? '私人仓' : '目的仓待定' },
|
||||
startScanner() { this.stopScanner(); this._stopScanner = startScanBroadcast({ onScan: (value) => this.handlePalletScan(value), onError: (error) => { this.error = error } }) },
|
||||
stopScanner() { if (this._stopScanner) this._stopScanner(); this._stopScanner = null },
|
||||
handlePalletScan(value) { const pallet = this.pallets.find((item) => item.key === this.activePalletKey && item.generated && !item.bound); if (!pallet) return; pallet.bindCode = String(value || '').trim(); this.bindPallet(pallet) },
|
||||
@@ -152,7 +154,7 @@ export default {
|
||||
async loadCandidates() { this.loading = true; this.error = null; try { this.candidates = await listWarehouseTransferCandidates() } catch (e) { this.error = e } finally { this.loading = false } },
|
||||
async select(item) {
|
||||
if (this.detailLoading || this.submitting) return
|
||||
this.detailLoading = true; this.error = null; this.success = false; this.completedPallets = []; this.completedTransferNo = ''; this.completedDestination = ''
|
||||
this.detailLoading = true; this.error = null; this.success = false; this.completedPallets = []; this.completedTransferNo = ''; this.completedDestination = ''; this.completedDestinationType = ''
|
||||
try { this.selected = await getWarehouseTransferDetail(item.transferNo); this.pendingKey = ''; this.pallets = this.selected.pallets?.length ? this.selected.pallets.map(restoredPallet) : [newPallet()]; await this.restorePhotos(item.transferNo, this.selected.measurementPhotos) }
|
||||
catch (e) { this.selected = null; this.error = e }
|
||||
finally { this.detailLoading = false }
|
||||
@@ -195,7 +197,7 @@ export default {
|
||||
try {
|
||||
if (!this.pendingKey) this.pendingKey = `pda-transfer-${this.selected.transferNo}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`
|
||||
const payload = { idempotencyKey: this.pendingKey, photoFileIds: [...this.photoFileIds] }
|
||||
const transferNo = this.selected.transferNo; const result = await palletizeWarehouseTransfer(transferNo, payload); this.completedTransferNo = transferNo; this.completedDestination = result?.fbaWarehouseCode || this.selected.fbaWarehouseCode || ''; this.completedPallets = (result?.pallets || []).filter((pallet) => pallet?.palletNo); this.success = true; this.selected = null; this.pendingKey = ''; this.pallets = [newPallet()]; this.photoFileIds = []; this.photoUrls = {}; this.photoNames = []; await this.loadCandidates()
|
||||
const transferNo = this.selected.transferNo; const result = await palletizeWarehouseTransfer(transferNo, payload); this.completedTransferNo = transferNo; this.completedDestination = result?.fbaWarehouseCode || this.selected.fbaWarehouseCode || ''; this.completedDestinationType = result?.destinationType || this.selected.destinationType || ''; this.completedPallets = (result?.pallets || []).filter((pallet) => pallet?.palletNo); this.success = true; this.selected = null; this.pendingKey = ''; this.pallets = [newPallet()]; this.photoFileIds = []; this.photoUrls = {}; this.photoNames = []; await this.loadCandidates()
|
||||
} catch (e) { this.error = e } finally { this.submitting = false }
|
||||
},
|
||||
async printPallet(pallet) { if (!pallet?.labelDownloadPath) { this.error = new Error('服务端未返回托盘标签下载地址,请刷新后重试'); return }; await this.openLabelPdf(() => downloadWarehouseTransferPalletLabel(pallet.labelDownloadPath)) },
|
||||
|
||||
@@ -79,8 +79,10 @@ test('warehouse transfer restores uploaded photos and exposes honest pallet labe
|
||||
assert.match(page, /completedPallets = \(result\?\.pallets \|\| \[\]\)/)
|
||||
assert.match(page, /downloadWarehouseTransferPalletLabel/)
|
||||
assert.match(page, /pallet\.labelDownloadPath/)
|
||||
assert.match(page, /pallet\.fbaWarehouseCode \|\| completedDestination \|\| '目的仓待定'/)
|
||||
assert.match(page, /目的仓待定/)
|
||||
assert.match(page, /destinationLabel\(pallet, \{ destinationType: completedDestinationType \}\)/)
|
||||
assert.match(page, /type === 'PRIVATE' \? '私人仓' : '目的仓待定'/)
|
||||
assert.match(page, /completedDestinationType = result\?\.destinationType \|\| this\.selected\.destinationType/)
|
||||
assert.doesNotMatch(page, /privateDestinationAddress/)
|
||||
assert.match(page, /uni\.openDocument\(\{ filePath, fileType: 'pdf', showMenu: true/)
|
||||
assert.doesNotMatch(page, /批量打印|printAllPallets/)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user