优化
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="work-card">
|
||||
<text class="card-title">箱与箱合并</text>
|
||||
<text class="card-title">包裹/箱合箱</text>
|
||||
<text v-if="plan" class="business-code">{{ plan.planNo }}</text>
|
||||
<text v-if="plan && plan.remark" class="hint plan-remark">合箱备注:{{ plan.remark }}</text>
|
||||
<view class="choice-row"><button class="secondary" @tap="choose('NEW')">{{ mode === 'NEW' ? '✓ ' : '' }}新增箱子</button><button class="secondary" @tap="choose('EXISTING')">{{ mode === 'EXISTING' ? '✓ ' : '' }}使用已有箱子</button></view>
|
||||
<view class="choice-row"><button class="secondary" @tap="choose('NEW')">{{ mode === 'NEW' ? '✓ ' : '' }}新增箱子</button><button v-if="!plan || plan.mode !== 'SKU'" class="secondary" @tap="choose('EXISTING')">{{ mode === 'EXISTING' ? '✓ ' : '' }}使用已有箱子</button></view>
|
||||
<text class="hint">{{ mode === 'NEW' ? '从下方来源箱选择 SKU 和扣除数量,完成后生成新箱唛。' : '扫描来源箱,再扫描另一只箱作为目标;目标箱原有库存不扣除。' }}</text>
|
||||
<template v-if="mode === 'EXISTING' || (mode === 'NEW' && !plan)">
|
||||
<template v-if="mode">
|
||||
<ScanTargetInput name="source" v-model="sourceCode" label="来源箱唛" placeholder="扫描来源箱唛" :active="active === 'source'" @activate="active = 'source'" @submit="scanSource" />
|
||||
<button class="secondary" :disabled="busy || !mode || !sourceCode.trim()" @tap="scanSource(sourceCode)">{{ mode === 'EXISTING' && sources.length ? '确认更换来源箱' : '确认来源箱' }}</button>
|
||||
<view v-if="mode === 'EXISTING'" class="confirmed-sources">
|
||||
@@ -36,7 +36,8 @@
|
||||
</view>
|
||||
<view v-for="box in sources" :key="box.cartonMark" class="item-card section-gap">
|
||||
<view class="row-head"><text class="business-code">{{ box.cartonMark }}</text><button v-if="!plan" class="link-button" @tap="remove(box.cartonMark)">移除</button></view>
|
||||
<view v-for="item in box.items" :key="item.skuCode" class="source-quantity"><text class="meta-line">{{ item.skuCode }} · 可扣 {{ item.quantity }} 件</text><input class="small-input" type="number" :value="deduction(box.cartonMark,item.skuCode)" placeholder="扣除数量" @input="setDeduction(box.cartonMark,item.skuCode,$event.detail.value)" /></view>
|
||||
<template v-if="!plan"><button class="secondary" @tap="printSource(box.cartonMark)">补打包裹/箱标签</button><ReturnLabelConfirmation ref="sourceLabels" :carton-mark="box.cartonMark" /></template>
|
||||
<view v-for="item in box.items" :key="item.skuCode" class="source-quantity"><text class="meta-line">{{ item.skuCode }} · 可扣 {{ item.quantity }} 件</text><input class="small-input" type="number" :disabled="plan?.mode === 'SKU'" :value="deduction(box.cartonMark,item.skuCode)" placeholder="扣除数量" @input="setDeduction(box.cartonMark,item.skuCode,$event.detail.value)" /></view>
|
||||
</view>
|
||||
<button class="primary" :disabled="!canComplete" @tap="complete">{{ busy ? '处理中…' : '确认合箱' }}</button>
|
||||
</view>
|
||||
@@ -45,16 +46,18 @@
|
||||
|
||||
<script>
|
||||
import ScanTargetInput from '@/components/ScanTargetInput.vue'
|
||||
import { scanReturnCarton, completePackingPlan, mergeReturnBoxes } from '@/api/return-packing.js'
|
||||
import ReturnLabelConfirmation from '@/components/ReturnLabelConfirmation.vue'
|
||||
import { scanReturnCarton, completePackingPlan, mergeReturnBoxes, getReturnCartonLabel } from '@/api/return-packing.js'
|
||||
import { updateWarehouseWork, warehouseWork, warehouseIdempotencyKey, releaseWarehouseKey } from '@/stores/warehouse-work.js'
|
||||
export default {
|
||||
components: { ScanTargetInput },
|
||||
components: { ScanTargetInput, ReturnLabelConfirmation },
|
||||
props: { plan: { type: Object, default: null }, initialSource: { type: Object, default: null } },
|
||||
emits: ['completed', 'error', 'busy-change'],
|
||||
data() { return { mode:'', dimensions:{length:'',width:'',height:'',weight:''}, fields:[{key:'length',label:'长 cm'},{key:'width',label:'宽 cm'},{key:'height',label:'高 cm'},{key:'weight',label:'重量 kg'}], sourceCode: '', targetCode: '', sources: [], target: null, deductions: {}, active: 'source', busy: false } },
|
||||
computed: { volume() { const value = Number(this.dimensions.length) * Number(this.dimensions.width) * Number(this.dimensions.height) / 1000000; return Number.isFinite(value) && value > 0 ? value.toFixed(6) : '0.000000' }, canComplete() { return !this.busy && this.plannedItems().length > 0 && (this.mode === 'NEW' ? this.fields.every(f => Number(this.dimensions[f.key]) > 0) : !!this.target && this.target.cartonMark === this.targetCode.trim() && this.sources[0]?.cartonMark === this.sourceCode.trim()) } },
|
||||
computed: { volume() { const value = Number(this.dimensions.length) * Number(this.dimensions.width) * Number(this.dimensions.height) / 1000000; return Number.isFinite(value) && value > 0 ? value.toFixed(6) : '0.000000' }, canComplete() { return !this.busy && (!this.plan || this.plan.mode !== 'SKU' || this.plan.sourceCartonMarks.every(mark => this.sources.some(box => box.cartonMark === mark))) && this.plannedItems().length > 0 && (this.mode === 'NEW' ? this.fields.every(f => Number(this.dimensions[f.key]) > 0) : !!this.target && this.target.cartonMark === this.targetCode.trim() && this.sources[0]?.cartonMark === this.sourceCode.trim()) } },
|
||||
async mounted() {
|
||||
if (!this.plan && this.initialSource) { this.choose('EXISTING'); this.sources = [this.initialSource]; this.sourceCode = this.initialSource.cartonMark; this.active = 'target'; return }
|
||||
if (!this.plan && this.initialSource) { this.choose('NEW'); this.sources = [this.initialSource]; this.sourceCode = ''; this.active = 'source'; return }
|
||||
this.choose('NEW')
|
||||
this.targetCode = warehouseWork.returnPacking.targetCode || ''
|
||||
const marks = this.plan?.sourceCartonMarks || warehouseWork.returnPacking.sourceCartonMarks || []
|
||||
if (this.plan) {
|
||||
@@ -65,7 +68,7 @@ export default {
|
||||
} else for (const mark of marks) await this.scanSource(mark)
|
||||
},
|
||||
methods: {
|
||||
choose(mode) { if(this.busy || this.mode === mode) return; const current = !this.plan ? (this.sources[0] || this.initialSource) : null; this.mode=mode; this.sources=mode === 'NEW' && this.plan ? (this.plan.sources || []).map(box => ({...box,customerId:this.plan.customerId})) : current ? [current] : []; this.target=null; this.targetCode=''; this.sourceCode=mode === 'EXISTING' && current ? current.cartonMark : ''; this.deductions={}; this.active=mode === 'NEW' && this.plan ? '' : mode === 'EXISTING' && current ? 'target' : 'source' },
|
||||
choose(mode) { if(this.busy || this.mode === mode) return; const current = !this.plan ? (this.sources[0] || this.initialSource) : null; this.mode=mode; this.sources=current ? [current] : []; this.target=null; this.targetCode=''; this.sourceCode=mode === 'EXISTING' && current ? current.cartonMark : ''; this.deductions={}; this.active=mode === 'EXISTING' && current ? 'target' : 'source' },
|
||||
save() { updateWarehouseWork('returnPacking', { sourceCartonMarks: this.sources.map(box => box.cartonMark), targetCode: this.targetCode }) },
|
||||
remove(mark) { this.sources = this.sources.filter(box => box.cartonMark !== mark); this.save() },
|
||||
async scanSource(raw) {
|
||||
@@ -85,6 +88,7 @@ export default {
|
||||
if (this.mode === 'EXISTING') {
|
||||
this.sources = [box]; this.sourceCode = mark; this.deductions = {}; this.target = null; this.targetCode = ''
|
||||
} else { this.sources.push(box); this.sourceCode = '' }
|
||||
if (this.plan?.mode === 'SKU') this.deductions = { ...this.deductions, [mark]: Object.fromEntries((box.items || []).map(item => [item.skuCode, Number(item.quantity)])) }
|
||||
this.save(); this.active = this.mode === 'NEW' ? 'source' : 'target'
|
||||
})
|
||||
},
|
||||
@@ -111,7 +115,18 @@ export default {
|
||||
this.target = box; this.save()
|
||||
})
|
||||
},
|
||||
acceptScan(value) { if (!this.active) return; return this.active === 'source' ? this.scanSource(value) : this.scanTarget(value) },
|
||||
acceptScan(value) { if (!this.plan && this.sources.some(box => box.cartonMark === String(value).trim())) { for (const label of [].concat(this.$refs?.sourceLabels || [])) label.acceptScan(value); return } if (!this.active) return; return this.active === 'source' ? this.scanSource(value) : this.scanTarget(value) },
|
||||
async printSource(mark) {
|
||||
// #ifdef H5
|
||||
const tab = window.open('', '_blank')
|
||||
if (!tab) { this.$emit('error', new Error('请允许打开标签打印窗口')); return }
|
||||
try { const label = await getReturnCartonLabel(mark); tab.document.write(label.printableHtml); tab.document.close(); tab.focus(); tab.print() }
|
||||
catch (error) { tab.close(); this.$emit('error', error) }
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
this.$emit('error', new Error('当前设备未配置打印服务'))
|
||||
// #endif
|
||||
},
|
||||
deduction(mark, sku) { return this.deductions?.[mark]?.[sku] || '' },
|
||||
setDeduction(mark, sku, raw) {
|
||||
const box = this.sources.find(item => item.cartonMark === mark)
|
||||
|
||||
Reference in New Issue
Block a user