@@ -90,6 +90,7 @@
< / template >
< / view >
< button v-if = "cartonsCounted" class="add-pallet-button" @tap="printCartonLabels" > 打开箱标签打印 < / button >
< button v-if = "restorableCartons.length" class="add-pallet-button" :disabled="countingCartons || submitting || deletingCarton" @tap="restoreDeletedCarton" > 恢复已删除箱子 ( {{ restorableCartons.length }} ) < / button >
< button class = "transfer-primary" : disabled = "!allCartonsConfirmed || !cartonCountReady || countingCartons || cartonsCounted" @tap ="confirmCartons" > {{ cartonsCounted ? ' 全部箱子已清点 ' : countingCartons ? ' 保存中 … ' : ' 保存全部清点结果 ' }} < / button >
< / view >
< view class = "photo-card" >
@@ -138,8 +139,17 @@ const restoredPallet = (value, index) => ({
export default {
components : { PortalHeader , ScanTargetInput , CartonCountFields } ,
data ( ) { return { summaryCollapsed : false , receivingPalletId : '' , cartonPalletFilter : '' , batchPalletId : '' , batchCountOpen : false , batchSku : '' , batchBox : newBatchBox ( ) , batchSelectedIndexes : [ ] , batchCountMessage : '' , cartonScrollTarget : '' , cartonBoxes : [ ] , countDiscrepancyReason : '' , countingCartons : false , cartonRequestKey : '' , cartonSignature : '' , user : session . currentUser , entryMode : 'work' , pendingTaskNo : '' , candidates : [ ] , selected : null , pallets : [ newPallet ( ) ] , activePalletKey : '' , photoFileIds : [ ] , photoNames : [ ] , photoUrls : { } , completedPallets : [ ] , completedTransferNo : '' , completedDestination : '' , completedDestinationType : '' , loading : false , detailLoading : false , submitting : false , uploadingPhoto : false , openingLabel : false , error : null , success : false , pendingKey : '' } } ,
data ( ) { return { deletedCartonBoxes : [ ] , deletingCarton : false , summaryCollapsed : false , receivingPalletId : '' , cartonPalletFilter : '' , batchPalletId : '' , batchCountOpen : false , batchSku : '' , batchBox : newBatchBox ( ) , batchSelectedIndexes : [ ] , batchCountMessage : '' , cartonScrollTarget : '' , cartonBoxes : [ ] , countDiscrepancyReason : '' , countingCartons : false , cartonRequestKey : '' , cartonSignature : '' , user : session . currentUser , entryMode : 'work' , pendingTaskNo : '' , candidates : [ ] , selected : null , pallets : [ newPallet ( ) ] , activePalletKey : '' , photoFileIds : [ ] , photoNames : [ ] , photoUrls : { } , completedPallets : [ ] , completedTransferNo : '' , completedDestination : '' , completedDestinationType : '' , loading : false , detailLoading : false , submitting : false , uploadingPhoto : false , openingLabel : false , error : null , success : false , pendingKey : '' } } ,
computed : {
restorableCartons ( ) {
const current = new Set ( this . cartonBoxes . map ( box => box . cartonMark || box . localKey ) ) ;
const removed = new Map ( ) ;
for ( const box of [ ... ( this . selected ? . cartons || [ ] ) , ... this . deletedCartonBoxes ] ) {
const key = box . cartonMark || box . localKey ;
if ( key && ! current . has ( key ) ) removed . set ( key , box ) ;
}
return [ ... removed . values ( ) ] ;
} ,
generatedPallets ( ) { return this . pallets . filter ( pallet => pallet . generated && pallet . draftId ) } ,
declaredSkuCodes ( ) { return [ ... new Set ( ( this . selected ? . items || [ ] ) . map ( item => item . skuCode ) ) ] } ,
batchSkuCodes ( ) { return [ ... new Set ( this . receivedCartonBoxes . map ( box => box . items [ 0 ] ? . skuCode ) . filter ( Boolean ) ) ] } ,
@@ -186,7 +196,7 @@ export default {
} ,
watch : {
countDiscrepancyReason ( ) { this . saveCartonDraft ( ) } ,
cartonBoxes : { deep : true , handler ( ) { if ( this . selected && ! this . cartonsCounted ) uni . setStorageSync ( this . cartonDraftKey ( ) , { boxes : this . cartonBoxes , forecastMarks : ( this . selected . cartons || [ ] ) . map ( box => box . cartonMark ) , discrepancyReason : this . countDiscrepancyReason , key : this . cartonRequestKey , signature : this . cartonSignature } ) } } ,
cartonBoxes : { deep : true , handler ( ) { if ( this . selected && ! this . cartonsCounted ) uni . setStorageSync ( this . cartonDraftKey ( ) , { boxes : this . cartonBoxes , deletedBoxes : this . deletedCartonBoxes , forecastMarks : ( this . selected . cartons || [ ] ) . map ( box => box . cartonMark ) , discrepancyReason : this . countDiscrepancyReason , key : this . cartonRequestKey , signature : this . cartonSignature } ) } } ,
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 ) { const fromExplicitTask = Boolean ( this . pendingTaskNo ) ; this . pendingTaskNo = '' ; void this . select ( active , fromExplicitTask ) } } } ) } } ,
@@ -214,7 +224,7 @@ export default {
this . countingCartons = true ; this . error = null
try {
const detail = await reopenWarehouseTransferMeasurement ( this . selected . transferNo )
uni . removeStorageSync ( this . cartonDraftKey ( ) ) ; this . selected = detail ; this . restoreCartons ( )
uni . setStorageSync ( this . cartonDraftKey ( ) , { deletedBoxes : this . deletedCartonBoxes } ) ; this . selected = detail ; this . restoreCartons ( )
this . cartonBoxes . forEach ( current => { current . confirmedSignature = current . cartonMark === mark ? '' : this . cartonConfirmationSignature ( current ) } )
this . pendingKey = '' ; this . saveCartonDraft ( )
} catch ( error ) { this . error = error } finally { this . countingCartons = false }
@@ -267,13 +277,14 @@ export default {
if ( ! target || target . received === false || ! this . validCartonValues ( source ) ) return ;
this . copyCartonValues ( source , target ) ; this . saveCartonDraft ( ) ;
} ,
saveCartonDraft ( ) { if ( this . selected && ! this . cartonsCounted ) uni . setStorageSync ( this . cartonDraftKey ( ) , { boxes : this . cartonBoxes , forecastMarks : ( this . selected . cartons || [ ] ) . map ( box => box . cartonMark ) , discrepancyReason : this . countDiscrepancyReason , key : this . cartonRequestKey , signature : this . cartonSignature } ) } ,
saveCartonDraft ( ) { if ( this . selected && ! this . cartonsCounted ) uni . setStorageSync ( this . cartonDraftKey ( ) , { boxes : this . cartonBoxes , deletedBoxes : this . deletedCartonBoxes , forecastMarks : ( this . selected . cartons || [ ] ) . map ( box => box . cartonMark ) , discrepancyReason : this . countDiscrepancyReason , key : this . cartonRequestKey , signature : this . cartonSignature } ) } ,
cartonDraftKey ( ) { return ` transfer-carton-count: ${ session . apiBase } : ${ this . user ? . id } : ${ this . user ? . warehouseId } : ${ this . selected ? . transferNo } ` } ,
restoreCartons ( ) {
const rows = ( this . selected ? . cartons || [ ] ) . filter ( box => box . status !== 'NOT_RECEIVED' ) . map ( box => ( { ... box , transferPalletId : box . transferPalletId || ( this . generatedPallets . length === 1 ? this . generatedPallets [ 0 ] . draftId : '' ) , received : box . status !== 'NOT_RECEIVED' , items : box . items ? . length ? box . items . map ( line => ( { skuCode : line . skuCode , quantity : line . quantity } ) ) : [ { skuCode : this . selected . items . find ( item => String ( item . id ) === String ( box . transferItemId ) ) ? . skuCode || this . declaredSkuCodes [ 0 ] || '' , quantity : box . quantity ? ? '' } ] } ) ) ;
const draft = uni . getStorageSync ( this . cartonDraftKey ( ) ) ;
this . deletedCartonBoxes = Array . isArray ( draft ? . deletedBoxes ) ? draft . deletedBoxes . filter ( box => ! box . cartonMark || ( this . selected ? . cartons || [ ] ) . some ( row => row . cartonMark === box . cartonMark ) ) : [ ] ;
this . countDiscrepancyReason = this . selected ? . cartons ? . find ( box => box . discrepancyReason ) ? . discrepancyReason || '' ; this . cartonRequestKey = '' ; this . cartonSignature = '' ;
if ( ! this . cartonsCounted && Array . isArray ( draft ? . boxes ) && draft . boxes . every ( box => box . items ? . length && box . items . every ( line => this . declaredSkuCodes . includes ( line . skuCode ) ) && ( box . cartonMark || this . selected . items . some ( item => String ( item . id ) === String ( box . transferItemId ) ) ) ) && draft . boxes . every ( box => ! box . cartonMark || rows . some ( row => row . cartonMark === box . cartonMark ) ) ) {
if ( ! this . cartonsCounted && Array . isArray ( draft ? . boxes ) && draft . boxes . every ( box => box . items ? . length && box . items . every ( line => this . declaredSkuCodes . includes ( line . skuCode ) ) && ( box . cartonMark || this . selected . items . some ( item => String ( item . id ) === String ( box . transferItemId ) ) ) ) && draft . boxes . every ( box => ! box . cartonMark || ( this . selected ? . cartons || [ ] ) . some ( row => row . cartonMark === box . cartonMark ) ) ) {
const knownMarks = new Set ( draft . forecastMarks || draft . boxes . map ( box => box . cartonMark ) ) ;
this . cartonBoxes = [ ... draft . boxes , ... rows . filter ( box => ! knownMarks . has ( box . cartonMark ) ) ] ; this . countDiscrepancyReason = draft . discrepancyReason || '' ; this . cartonRequestKey = draft . key || '' ; this . cartonSignature = draft . signature || '' ;
} else this . cartonBoxes = rows ;
@@ -291,9 +302,36 @@ export default {
this . error = new Error ( '当前设备未配置箱标签打印服务' ) ;
// #endif
} ,
removeCarton ( index ) {
if ( this . cartonsCounted || this . countingCartons ) return ;
this . cartonBoxes . splice ( index , 1 ) ; this . batchSelectedIndexes = [ ] ; this . batchCountMessage = '' ; this . saveCartonDraft ( ) ;
async removeCarton ( index ) {
if ( this . cartonsCounted || this . countingCartons || this . submitting || this . deletingCarton ) return ;
const box = this . cartonBoxes [ index ] , transferNo = this . selected ? . transferNo ;
if ( ! box ) return ;
this . deletingCarton = true ;
try {
const answer = await new Promise ( ( resolve , reject ) => uni . showModal ( { title : '确认删除箱子' , content : ` 确定删除 ${ box . cartonMark || ` 第 ${ index + 1 } 箱 ` } 吗?删除后本箱不计入本次实收,保存清点时会记为未收到。误删可通过“恢复已删除箱子”找回。 ` , confirmText : '确认删除' , confirmColor : '#b74545' , cancelText : '取消' , success : resolve , fail : reject } ) ) ;
if ( ! answer . confirm || transferNo !== this . selected ? . transferNo || this . cartonsCounted || this . countingCartons || this . submitting ) return ;
const position = this . cartonBoxes . indexOf ( box ) ;
if ( position < 0 ) return ;
if ( ! box . cartonMark && ! box . localKey ) box . localKey = ` removed- ${ Date . now ( ) } - ${ Math . random ( ) } ` ;
this . deletedCartonBoxes . push ( box ) ; this . cartonBoxes . splice ( position , 1 ) ;
this . batchSelectedIndexes = [ ] ; this . batchCountMessage = '' ; this . saveCartonDraft ( ) ;
} catch ( error ) { this . error = error } finally { this . deletingCarton = false }
} ,
async restoreDeletedCarton ( ) {
if ( this . countingCartons || this . submitting || this . deletingCarton || ! this . restorableCartons . length ) return ;
const candidates = this . restorableCartons , transferNo = this . selected ? . transferNo ;
try {
const choice = candidates . length === 1 ? 0 : await new Promise ( ( resolve , reject ) => uni . showActionSheet ( { itemList : candidates . map ( ( box , index ) => box . cartonMark || ` 已删除实收箱 ${ index + 1 } ` ) , success : result => resolve ( result . tapIndex ) , fail : ( ) => resolve ( - 1 ) } ) ) ;
if ( choice < 0 || transferNo !== this . selected ? . transferNo ) return ;
const removed = candidates [ choice ] , key = removed . cartonMark || removed . localKey ;
if ( this . cartonsCounted ) { await this . remeasure ( ) ; if ( this . cartonsCounted || transferNo !== this . selected ? . transferNo ) return }
if ( this . cartonBoxes . some ( box => ( box . cartonMark || box . localKey ) === key ) ) return ;
const box = { ... removed , received : true , status : 'EXPECTED' , countedAt : null , confirmedSignature : '' ,
items : removed . items ? . length ? removed . items . map ( line => ( { ... line } ) ) : [ { skuCode : this . selected . items . find ( item => String ( item . id ) === String ( removed . transferItemId ) ) ? . skuCode || this . declaredSkuCodes [ 0 ] || '' , quantity : removed . quantity ? ? '' } ] } ;
if ( ! this . generatedPallets . some ( pallet => String ( pallet . draftId ) === String ( box . transferPalletId ) ) ) box . transferPalletId = this . receivingPalletId || this . generatedPallets [ 0 ] ? . draftId || '' ;
this . deletedCartonBoxes = this . deletedCartonBoxes . filter ( item => ( item . cartonMark || item . localKey ) !== key ) ;
this . cartonBoxes . push ( box ) ; this . cartonPalletFilter = '' ; this . cartonRequestKey = '' ; this . cartonSignature = '' ; this . saveCartonDraft ( ) ;
} catch ( error ) { this . error = error }
} ,
addExtraCarton ( ) {
if ( this . cartonsCounted || this . countingCartons || ! this . selected ? . items ? . length ) return ;
@@ -316,10 +354,10 @@ export default {
const boxes = this . receivedCartonBoxes . map ( box => ( { cartonMark : box . cartonMark || null , transferItemId : box . cartonMark ? box . transferItemId : this . selected . items . find ( item => item . skuCode === box . items [ 0 ] ? . skuCode ) ? . id , transferPalletId : box . transferPalletId , length : Number ( box . length ) , width : Number ( box . width ) , height : Number ( box . height ) , weight : Number ( box . weight ) , items : box . items . map ( line => ( { skuCode : line . skuCode , quantity : Number ( line . quantity ) } ) ) } ) ) ;
const signature = JSON . stringify ( { boxes , discrepancyReason : this . countDiscrepancyReason , forecastPackageCount : Number ( this . selected . packageCount ) } ) ;
if ( ! this . cartonRequestKey || signature !== this . cartonSignature ) { this . cartonRequestKey = ` transfer-count- ${ Date . now ( ) } - ${ Math . random ( ) . toString ( 36 ) . slice ( 2 ) } ` ; this . cartonSignature = signature }
uni . setStorageSync ( this . cartonDraftKey ( ) , { boxes : this . cartonBoxes , forecastMarks : ( this . selected . cartons || [ ] ) . map ( box => box . cartonMark ) , discrepancyReason : this . countDiscrepancyReason , key : this . cartonRequestKey , signature } ) ;
uni . setStorageSync ( this . cartonDraftKey ( ) , { boxes : this . cartonBoxes , deletedBoxes : this . deletedCartonBoxes , forecastMarks : ( this . selected . cartons || [ ] ) . map ( box => box . cartonMark ) , discrepancyReason : this . countDiscrepancyReason , key : this . cartonRequestKey , signature } ) ;
const detail = await countWarehouseTransferCartons ( this . selected . transferNo , { idempotencyKey : this . cartonRequestKey , boxes , discrepancyReason : this . countDiscrepancyReason , forecastPackageCount : Number ( this . selected . packageCount ) } ) ;
if ( ! detail . cartons ? . length || ! detail . cartons . every ( box => box . countedAt ) ) throw new Error ( '清点结果未确认,请刷新核实' ) ;
uni . removeStorageSync ( this . cartonDraftKey ( ) ) ; this . selected = detail ; this . pallets = detail . pallets . map ( restoredPallet ) ; this . restoreCartons ( ) ;
uni . setStorageSync ( this . cartonDraftKey ( ) , { deletedBoxes : this . deletedCartonBoxes } ) ; this . selected = detail ; this . pallets = detail . pallets . map ( restoredPallet ) ; this . restoreCartons ( ) ;
} catch ( error ) { this . error = error } finally { this . countingCartons = false }
} ,
openPalletOperations ( ) { uni . navigateTo ( { url : '/pages/pallet/pallet' } ) } ,
@@ -415,7 +453,7 @@ export default {
this . countingCartons = true ; this . error = null ;
try {
const detail = await reopenWarehouseTransferMeasurement ( this . selected . transferNo ) ;
uni . removeStorageSync ( this . cartonDraftKey ( ) ) ; this . selected = detail ; this . restoreCartons ( ) ; this . pendingKey = '' ;
uni . setStorageSync ( this . cartonDraftKey ( ) , { deletedBoxes : this . deletedCartonBoxes } ) ; this . selected = detail ; this . restoreCartons ( ) ; this . pendingKey = '' ;
this . cartonScrollTarget = 'transfer-boxes' ;
} catch ( error ) { this . error = error } finally { this . countingCartons = false }
} ,