This commit is contained in:
2026-11-04 14:39:28 +08:00
parent 55cdca5444
commit b298a4b69d
2 changed files with 25 additions and 6 deletions
+5 -1
View File
@@ -2,7 +2,7 @@
<scroll-view class="work-scroll" scroll-y><view class="portal-content work-content">
<view v-if="error" class="work-card"><text role="alert">{{ error }}</text><button :disabled="busy" @tap="refresh">刷新任务</button></view>
<template v-if="!current">
<view class="row-head"><text class="card-title">异常退货入库</text><button :disabled="busy" @tap="refresh">刷新</button></view>
<view class="row-head"><button class="refresh-button" :disabled="busy" @tap="refresh">刷新</button></view>
<text v-if="!busy && !tasks.length" class="empty-copy">当前仓没有待验收异常退货任务</text>
<view v-for="task in tasks" :key="task.exceptionNo" class="work-card">
<text class="business-code">{{ task.exceptionNo }}</text>
@@ -66,6 +66,10 @@ export default {
}
</script>
<style scoped>
.work-scroll { flex: 1; height: 0; min-height: 0; }
.work-content { padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
.row-head { display: flex; justify-content: flex-end; margin-bottom: 12px; }
.refresh-button { margin: 0; padding: 0 16px; border: 1px solid #b8d1f5; border-radius: 8px; color: #135ee8; background: #f8fbff; }
.work-card { margin: 12px 0; padding: 14px; border: 1px solid #dfe7ef; border-radius: 12px; background: #fff; }
.business-code,.meta-line,.card-title { display: block; margin-bottom: 10px; }
.business-code,.card-title { font-weight: 700; }.meta-line { color: #61758b; font-size: 13px; }
+20 -5
View File
@@ -1,7 +1,10 @@
<template>
<view v-if="user" class="page-shell portal-page work-page" :class="{ 'pda-task-list receipt-lookup-page': receiptDomain === 'customer' && !current && !result }">
<view v-if="user" class="page-shell portal-page work-page receipt-page" :class="{ 'pda-task-list receipt-lookup-page': receiptDomain === 'customer' && !current && !result }">
<PortalHeader title="退货入库" :user="user" />
<view class="row-head" style="padding: 10px"><button :disabled="busy" @tap="switchDomain('exception')">异常退货入库</button><button :disabled="busy" @tap="switchDomain('customer')">客户退货入库</button></view>
<view class="receipt-domain-tabs" role="tablist" aria-label="退货入库类型">
<button :class="['receipt-domain-tab', { active: receiptDomain === 'customer' }]" role="tab" :aria-selected="receiptDomain === 'customer'" :disabled="busy" @tap="switchDomain('customer')">客户退货入库</button>
<button :class="['receipt-domain-tab', { active: receiptDomain === 'exception' }]" role="tab" :aria-selected="receiptDomain === 'exception'" :disabled="busy" @tap="switchDomain('exception')">异常退货入库</button>
</view>
<ExceptionReturnWork v-if="receiptDomain === 'exception'" />
<scroll-view v-if="receiptDomain === 'customer'" class="work-scroll" scroll-y><view class="portal-content work-content">
<view v-if="!current && !result" class="work-card receipt-lookup-card">
@@ -60,7 +63,7 @@
<view v-if="current.completedPallets?.length" class="work-card"><text class="card-title">本单已完成打托</text><view class="item-list"><view v-for="pallet in current.completedPallets" :key="pallet.palletCode" class="item-card"><text class="business-code">{{ pallet.palletCode }}</text><text class="meta-line">{{ pallet.skuCode }} · {{ pallet.quantity }} 件</text><text class="meta-line">签收批次:{{ pallet.receiptBatchNo }}</text></view></view></view>
</template>
<view v-if="result" class="success-box result-card"><text class="success-title">退货签收成功</text><view v-if="result.labels?.length"><view v-for="(label,index) in result.labels" :key="label.cartonMark" class="item-card"><text class="business-code">第 {{ index + 1 }} {{ result.unitType === 'PARCEL' ? '包裹' : '箱' }} · {{ label.cartonMark }}</text><button class="secondary" @tap="printReturnCarton(label)">打印包裹/箱标签</button><text class="meta-line">签收已默认贴标</text></view></view><view v-else-if="result.printableHtml" class="item-card"><text class="business-code">{{ result.unitType === 'PALLET' ? '托盘标签' : '箱唛' }} · {{ result.cartonMark }}</text><button class="secondary" @tap="printReturnCarton(result)">打印{{ result.unitType === 'PALLET' ? '托盘标签' : '箱唛' }}</button></view><button v-if="result.unitType === 'PALLET' && result.labels?.length" class="secondary" :disabled="busy" @tap="goCount">去箱内清点</button><text v-if="result.palletCode" class="result-carton">托盘:{{ result.palletCode }}</text><text class="meta-line">签收单:{{ result.receiptNo }}</text><text class="meta-line">计费批次:{{ result.receiptBatchNo }}</text><view class="metric-row"><view class="metric"><strong>{{ result.receivedQuantity }}/{{ result.expectedQuantity }}</strong><text>整单累计</text></view><view class="metric"><strong>{{ result.fullyMatched ? '已完成' : '签收中' }}</strong><text>退货单状态</text></view></view><button class="primary" :disabled="busy" @tap="nextReceipt">{{ result.continuationReturnNo ? (unitType === 'PALLET' ? '新增托盘,继续签收剩余货物' : '继续签收本单剩余货物') : '签收下一单' }}</button><button v-if="unitType === 'PALLET' && result.continuationReturnNo" class="secondary" :disabled="busy" @tap="continueScanning">继续签收</button></view>
<view v-if="result" class="success-box result-card"><view v-if="result.labels?.length"><view v-for="(label,index) in result.labels" :key="label.cartonMark" class="item-card"><text class="business-code">第 {{ index + 1 }} {{ result.unitType === 'PARCEL' ? '包裹' : '箱' }} · {{ label.cartonMark }}</text><button class="secondary" @tap="printReturnCarton(label)">打印包裹/箱标签</button></view></view><view v-else-if="result.printableHtml" class="item-card"><text class="business-code">{{ result.unitType === 'PALLET' ? '托盘标签' : '箱唛' }} · {{ result.cartonMark }}</text><button class="secondary" @tap="printReturnCarton(result)">打印{{ result.unitType === 'PALLET' ? '托盘标签' : '箱唛' }}</button></view><button v-if="result.unitType === 'PALLET' && result.labels?.length" class="secondary" :disabled="busy" @tap="goCount">去箱内清点</button><text v-if="result.palletCode" class="result-carton">托盘:{{ result.palletCode }}</text><view class="metric-row"><view class="metric"><strong>{{ result.receivedQuantity }}/{{ result.expectedQuantity }}</strong></view><view class="metric"><strong>{{ result.fullyMatched ? '已完成' : '签收中' }}</strong></view></view><button class="primary" :disabled="busy" @tap="nextReceipt">{{ result.continuationReturnNo ? (unitType === 'PALLET' ? '新增托盘,继续签收剩余货物' : '继续签收本单剩余货物') : '签收下一单' }}</button><button v-if="unitType === 'PALLET' && result.continuationReturnNo" class="secondary" :disabled="busy" @tap="continueScanning">继续签收</button></view>
<view v-if="error" class="error-box" role="alert"><text class="error-title">{{ error.message }}</text><text v-if="error.code">错误码:{{ error.code }}</text><text v-if="error.requestId">requestId:{{ error.requestId }}</text><text v-if="error.traceId">traceId:{{ error.traceId }}</text><button v-if="current" class="secondary" :disabled="busy" @tap="reloadCurrent">刷新退货单</button></view>
</view></scroll-view>
@@ -79,7 +82,7 @@
export default {
components: { PortalHeader, ScanTargetInput, ExceptionReturnWork },
data() { return { receiptDomain: 'exception', user: session.currentUser, current: null, candidates: null, result: null, receiptResults: [], selectedSku: '', palletCheck: null, newPalletHtml: '', unitType: 'PALLET', unitCode: '', boxRows: [{ items: {}, length: '', width: '', height: '', weight: '', originalPackaging: true, confirmed: false }], palletLength: '', palletWidth: '', palletHeight: '', palletWeight: '', unitOptions: [{ value: 'PALLET', label: '托盘' }, { value: 'BOX', label: '箱子' }, { value: 'PARCEL', label: '包裹' }], photoFileIds: [], photoNames: [], photoUrls: {}, activeTarget: 'lookup', busy: false, error: null } },
data() { return { receiptDomain: 'customer', user: session.currentUser, current: null, candidates: null, result: null, receiptResults: [], selectedSku: '', palletCheck: null, newPalletHtml: '', unitType: 'PALLET', unitCode: '', boxRows: [{ items: {}, length: '', width: '', height: '', weight: '', originalPackaging: true, confirmed: false }], palletLength: '', palletWidth: '', palletHeight: '', palletWeight: '', unitOptions: [{ value: 'PALLET', label: '托盘' }, { value: 'BOX', label: '箱子' }, { value: 'PARCEL', label: '包裹' }], photoFileIds: [], photoNames: [], photoUrls: {}, activeTarget: 'lookup', busy: false, error: null } },
computed: {
entryMode: { get() { return warehouseWork.returnReceipt.entryMode }, set(value) { updateWarehouseWork('returnReceipt', { entryMode: value }) } },
lookupCode: { get() { return warehouseWork.returnReceipt.lookupCode }, set(value) { updateWarehouseWork('returnReceipt', { lookupCode: value }) } },
@@ -99,7 +102,7 @@
onShow() { if (!requireSession()) return; this.user = session.currentUser; restoreWarehouseWork(`${this.user.id}:${this.user.warehouseId}`); this.entryMode = 'SKU'; if (this.receiptDomain === 'customer') this.startScanner(); if (this.receiptDomain === 'customer' && warehouseWork.returnReceipt.currentReturnNo && !this.current && !this.busy) this.openOrder(warehouseWork.returnReceipt.currentReturnNo, 'SKU', false) },
onHide() { this.stopScanner() }, onUnload() { this.stopScanner() }, beforeUnmount() { this.stopScanner() },
methods: {
switchDomain(value) { if (this.busy) return; this.stopScanner(); this.receiptDomain = value; if (value === 'customer') this.startScanner() },
switchDomain(value) { if (this.busy || this.receiptDomain === value) return; this.stopScanner(); this.receiptDomain = value; if (value === 'customer') this.startScanner() },
goCount() { const mark = this.result?.labels?.[0]?.cartonMark; if (mark) uni.navigateTo({ url: '/pages/return-counting/return-counting?cartonMark=' + encodeURIComponent(mark) }) },
selectUnitType(type) { if (this.busy) return; this.unitType = type; this.unitCode = ''; this.boxRows = [{ items: {}, length: '', width: '', height: '', weight: '', originalPackaging: true, confirmed: false }]; this.palletCheck = null; this.activeTarget = type === 'PALLET' ? 'pallet' : 'unit' },
resizeBoxRows(raw) { if (this.busy) return; const count = Math.floor(Number(raw) || 0); if (count < 1 || count > 100) return; this.boxRows = Array.from({ length: count }, (_, index) => this.boxRows[index] || { items: {}, length: '', width: '', height: '', weight: '', originalPackaging: true, confirmed: false }) },
@@ -247,6 +250,18 @@
.physical-unit-card{padding:12px!important;border:1px solid #d8e5f5!important;background:linear-gradient(145deg,#fff 0%,#f7faff 100%);box-shadow:0 4px 12px rgba(30,78,130,.08)}.unit-card-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.unit-card-tag{padding:3px 7px;border-radius:10px;background:#eaf2ff;color:#135ee8;font-size:10px;font-weight:700}.unit-dimension-grid{margin-top:0}.unit-volume{display:flex;align-items:baseline;justify-content:flex-end;gap:4px;margin-top:7px;color:#728197;font-size:10px}.unit-volume strong{color:#135ee8;font-size:15px}.packaging-choice{display:flex;align-items:center;gap:7px;margin-top:10px;padding-top:9px;border-top:1px solid #e6edf6;color:#52667e;font-size:11px}.packaging-choice>text{flex:1}.choice-button{width:42px!important;min-width:42px!important;height:28px!important;min-height:28px!important;margin:0!important;padding:0!important;border:1px solid #d1ddeb!important;border-radius:7px!important;background:#fff!important;color:#65768b!important;font-size:11px!important;line-height:28px!important}.choice-button.selected{border-color:#135ee8!important;background:#eaf2ff!important;color:#135ee8!important;font-weight:700}
.receipt-quantity-heading{display:flex;align-items:center;flex-wrap:nowrap;gap:8px;margin-bottom:10px}.receipt-quantity-heading .card-title{margin-bottom:0;white-space:nowrap}.unit-count-row{display:flex;align-items:center;gap:6px;margin-left:auto;flex-shrink:0;white-space:nowrap;color:#65768b;font-size:10px}.unit-count-row .number-input{box-sizing:border-box;width:48px;min-width:48px;height:30px;min-height:30px;margin:0;padding:0 4px;border-radius:6px;text-align:center;font-size:13px}.quantity-row .unit-quantity-input{width:88px;flex-shrink:0;font-size:12px}.physical-unit-card .quantity-row>text{min-width:0;overflow-wrap:anywhere}.unit-card-head .link-button{margin:0;padding:0;font-size:10px}
@import '../../styles/task-list.scss';
.receipt-page{display:flex;flex-direction:column}
.receipt-page :deep(.portal-header-shell){flex-shrink:0}
.receipt-page>.work-scroll{flex:1;height:0;min-height:0}
.receipt-page .work-content{padding-bottom:calc(24px + env(safe-area-inset-bottom))}
.receipt-page .summary-bar{position:static}
.receipt-domain-tabs{display:flex;flex-shrink:0;gap:4px;margin:10px 14px 0;padding:4px;border:1px solid #d8e4f5;border-radius:10px;background:#e8eff9}
.receipt-domain-tab{box-sizing:border-box;flex:1;min-width:0;min-height:40px;margin:0;padding:0 8px;border-radius:7px;color:#52677f;background:transparent;font-size:14px;line-height:40px}
.receipt-domain-tab::after{border:0}
.receipt-domain-tab.active{color:#135ee8;background:#fff;font-weight:700;box-shadow:0 1px 5px rgba(28,69,121,.1)}
.receipt-domain-tab[disabled]{opacity:.6}
.manual-complete{margin-top:12px}
.receipt-lookup-page{background:#f1f5fd}
.receipt-lookup-page .work-content{padding-top:14px}
.receipt-lookup-card,.receipt-candidate-empty{box-shadow:none}