| | |
| | | <el-page-header @back="goBack"> |
| | | <template #content> |
| | | <span class="title">åºåºæ£é确认 - {{ this.$route.query.orderNo }}</span> |
| | | <el-tag v-if="currentBatchNo" type="success" style="margin-left: 10px;"> |
| | | å½åæ¹æ¬¡: {{ currentBatchNo }} |
| | | </el-tag> |
| | | </template> |
| | | </el-page-header> |
| | | </div> |
| | | |
| | | <!-- æ¹æ¬¡æä½åºå --> |
| | | <div class="batch-operations"> |
| | | <el-card> |
| | | <div class="batch-actions"> |
| | | <el-button type="primary" @click="openBatchAllocateDialog">åæ¹åé
</el-button> |
| | | <el-select v-model="selectedBatchNo" placeholder="éæ©æ¹æ¬¡" @change="onBatchChange" style="width: 200px; margin-left: 10px;"> |
| | | <el-option |
| | | v-for="batch in batchList" |
| | | :key="batch.batchNo" |
| | | :label="`${batch.batchNo} (${batch.batchStatusText})`" |
| | | :value="batch.batchNo"> |
| | | </el-option> |
| | | </el-select> |
| | | <el-button type="info" @click="refreshBatchList">å·æ°æ¹æ¬¡</el-button> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æ«ç åºå --> |
| | |
| | | <el-button type="info" @click="openRevertSplitDialog">æ¤éæå
</el-button> |
| | | <el-button type="info" @click="handleEmptyPallet">å空箱</el-button> |
| | | <el-button type="primary" @click="openBatchReturnDialog">ååº</el-button> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æ¹æ¬¡æ±æ»ä¿¡æ¯ --> |
| | | <div class="batch-summary-area" v-if="currentBatchNo"> |
| | | <el-card> |
| | | <div class="batch-summary-info"> |
| | | <el-tag type="info">æ¹æ¬¡å·: {{ batchSummary.batchNo }}</el-tag> |
| | | <el-tag :type="getBatchStatusType(batchSummary.batchStatus)"> |
| | | {{ batchSummary.batchStatusText }} |
| | | </el-tag> |
| | | <el-tag type="warning">åé
æ°é: {{ batchSummary.batchQuantity }}</el-tag> |
| | | <el-tag type="success">宿æ°é: {{ batchSummary.completedQuantity }}</el-tag> |
| | | <el-tag type="danger">å©ä½æ°é: {{ batchSummary.remainingQuantity }}</el-tag> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | |
| | | <el-table-column type="selection" width="55"></el-table-column> |
| | | <el-table-column prop="materielCode" label="ç©æç¼ç " width="120"></el-table-column> |
| | | <el-table-column prop="pickedQty" label="å·²æ£æ°é" width="100"></el-table-column> |
| | | <el-table-column prop="locationCode" label="è´§ä½" width="100"></el-table-column> |
| | | <!-- <el-table-column prop="locationCode" label="è´§ä½" width="100"></el-table-column> --> |
| | | <el-table-column prop="currentBarcode" label="æ¡ç "></el-table-column> |
| | | </el-table> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <!-- åæ¹åé
å¼¹çª --> |
| | | <div v-if="showBatchAllocateDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>åæ¹åé
åºå</h3> |
| | | <el-button type="text" @click="closeBatchAllocateDialog" class="close-button">Ã</el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form :model="batchAllocateForm" :rules="batchAllocateFormRules" ref="batchAllocateFormRef" label-width="100px"> |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="batchAllocateForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="ç©ææç»" prop="orderDetailId"> |
| | | <el-select v-model="batchAllocateForm.orderDetailId" placeholder="éæ©ç©ææç»" style="width: 100%"> |
| | | <el-option |
| | | v-for="detail in allocatableDetails" |
| | | :key="detail.id" |
| | | :label="`${detail.materielCode} - éæ±:${detail.needOutQuantity} å·²åé
:${detail.allocatedQuantity} å¯åé
:${detail.availableQuantity}`" |
| | | :value="detail.id"> |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="åé
æ°é" prop="batchQuantity"> |
| | | <el-input-number |
| | | v-model="batchAllocateForm.batchQuantity" |
| | | :min="0.01" |
| | | :precision="2" |
| | | :step="1" |
| | | style="width: 100%" |
| | | placeholder="è¾å
¥åé
æ°é"> |
| | | </el-input-number> |
| | | </el-form-item> |
| | | <el-form-item label="å¯åé
æ°é"> |
| | | <el-input :value="getAvailableQuantity()" disabled></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeBatchAllocateDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleBatchAllocate" :loading="batchAllocateLoading">确认åé
</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æå
å¼¹çª --> |
| | |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="splitForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æ¹æ¬¡ç¼å·"> |
| | | <el-input v-model="splitForm.batchNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æçç¼å·"> |
| | | <el-input v-model="splitForm.palletCode" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="åæ¡ç " prop="originalBarcode"> |
| | | <el-input |
| | | v-model="splitForm.originalBarcode" |
| | | placeholder="æ«æåæ¡ç " |
| | | @keyup.enter.native="onSplitBarcodeScan" |
| | | @change="onSplitBarcodeScan" |
| | | clearable> |
| | | </el-input> |
| | | <div style="display: flex; align-items: center; gap: 10px;"> |
| | | <el-input |
| | | v-model="splitForm.originalBarcode" |
| | | placeholder="æ«æåæ¡ç " |
| | | @keyup.enter.native="onSplitBarcodeScan" |
| | | @change="onSplitBarcodeScan" |
| | | clearable |
| | | style="flex: 1;"> |
| | | </el-input> |
| | | <!-- æ°å¢ï¼æ¥çæå
é¾æé® --> |
| | | <el-button |
| | | type="primary" |
| | | @click="viewSplitChainFromSplit(splitForm.originalBarcode)" |
| | | :disabled="!splitForm.originalBarcode" |
| | | :loading="splitChainLoading"> |
| | | æ¥çæå
é¾ |
| | | </el-button> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="ç©æç¼ç "> |
| | | <el-input v-model="splitForm.materielCode" disabled></el-input> |
| | |
| | | <div class="custom-dialog-body"> |
| | | <el-form :model="revertSplitForm" :rules="revertSplitFormRules" ref="revertSplitFormRef" label-width="100px"> |
| | | <el-form-item label="æ°æ¡ç " prop="newBarcode"> |
| | | <el-input |
| | | v-model="revertSplitForm.newBarcode" |
| | | placeholder="æ«ææ°æ¡ç " |
| | | @keyup.enter.native="onRevertSplitBarcodeScan" |
| | | @change="onRevertSplitBarcodeScan" |
| | | clearable> |
| | | </el-input> |
| | | <div style="display: flex; align-items: center; gap: 10px;"> |
| | | <el-input |
| | | v-model="revertSplitForm.newBarcode" |
| | | placeholder="æ«ææ°æ¡ç " |
| | | @keyup.enter.native="onRevertSplitBarcodeScan" |
| | | @change="onRevertSplitBarcodeScan" |
| | | clearable |
| | | style="flex: 1;"> |
| | | </el-input> |
| | | <!-- æ°å¢ï¼æ¥çæå
é¾æé® --> |
| | | <el-button |
| | | type="primary" |
| | | @click="viewSplitChain(revertSplitForm.newBarcode)" |
| | | :disabled="!revertSplitForm.newBarcode"> |
| | | æ¥çæå
é¾ |
| | | </el-button> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- æ°å¢ï¼æå
é¾ç®è¦ä¿¡æ¯æ¾ç¤º --> |
| | | <div v-if="splitChainInfo.splitChain && splitChainInfo.splitChain.length > 0" |
| | | style="margin-top: 15px; padding: 10px; background: #f0f9ff; border-radius: 4px;"> |
| | | <div style="font-size: 14px; color: #606266;"> |
| | | <div>æå
é¾ä¿¡æ¯: å
± {{ splitChainInfo.totalSplitTimes }} 次æå
</div> |
| | | <div style="margin-top: 5px;"> |
| | | <el-tag |
| | | v-for="item in splitChainInfo.splitChain.slice(0, 3)" |
| | | :key="item.newBarcode" |
| | | :type="item.isReverted ? 'success' : 'primary'" |
| | | size="small" |
| | | style="margin-right: 5px;"> |
| | | {{ item.newBarcode }} ({{ item.splitQuantity }}) |
| | | </el-tag> |
| | | <span v-if="splitChainInfo.splitChain.length > 3" style="color: #909399;"> |
| | | ç {{ splitChainInfo.splitChain.length }} 个æ¡ç |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeRevertSplitDialog">åæ¶</el-button> |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æå
é¾ä¿¡æ¯å¼¹çª --> |
| | | <div v-if="showSplitChainDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog" style="width: 750px;"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>æå
é¾ä¿¡æ¯</h3> |
| | | <el-button type="text" @click="closeSplitChainDialog" class="close-button">Ã</el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <!-- æ°å¢ï¼æå
é¾è¯´æ --> |
| | | <div style="margin-bottom: 15px; padding: 10px; background: #f0f9ff; border-radius: 4px;"> |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div> |
| | | <div style="font-weight: bold; color: #303133;">æå
é¾è¯´æ</div> |
| | | <div style="font-size: 12px; color: #606266; margin-top: 5px;"> |
| | | å½åæ¾ç¤ºçæ¯ä» <el-tag type="primary" size="small">{{ splitChainInfo.originalBarcode }}</el-tag> å¼å§çæå
é¾ |
| | | <br>å
± {{ splitChainInfo.totalSplitTimes }} 次æå
æä½ï¼æ¶å {{ splitChainInfo.splitChain.length }} 个æ¡ç |
| | | </div> |
| | | </div> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | @click="findRootChain(splitChainInfo.originalBarcode)" |
| | | v-if="splitChainInfo.chainType !== 'root'"> |
| | | æ¥æ¾å®æ´æå
é¾ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div style="margin-bottom: 15px;"> |
| | | <el-tag type="info">æ»æå
次æ°: {{ splitChainInfo.totalSplitTimes }}</el-tag> |
| | | <el-tag type="warning" style="margin-left: 10px;"> |
| | | åå§æ¡ç : {{ splitChainInfo.originalBarcode }} |
| | | </el-tag> |
| | | <el-tag :type="splitChainInfo.chainType === 'root' ? 'success' : 'warning'" style="margin-left: 10px;"> |
| | | {{ splitChainInfo.chainType === 'root' ? '宿´é¾' : '忝é¾' }} |
| | | </el-tag> |
| | | </div> |
| | | |
| | | <el-table :data="splitChainInfo.splitChain" border height="300"> |
| | | <el-table-column type="index" label="åºå·" width="60" align="center"></el-table-column> |
| | | <el-table-column prop="splitTime" label="æå
æ¶é´" width="160"> |
| | | <template #default="scope"> |
| | | {{ formatDateTime(scope.row.splitTime) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="originalBarcode" label="åæ¡ç " width="140"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="scope.row.originalBarcode === splitChainInfo.rootBarcode ? 'success' : 'primary'" |
| | | size="small"> |
| | | {{ scope.row.originalBarcode }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="newBarcode" label="æ°æ¡ç " width="140"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="scope.row.isReverted ? 'info' : 'warning'" |
| | | size="small"> |
| | | {{ scope.row.newBarcode }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="splitQuantity" label="æå
æ°é" width="100" align="right"> |
| | | <template #default="scope"> |
| | | {{ scope.row.splitQuantity.toFixed(2) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="operator" label="æä½å" width="100"></el-table-column> |
| | | <el-table-column prop="isReverted" label="ç¶æ" width="80" align="center"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="scope.row.isReverted ? 'success' : 'danger'" |
| | | size="small"> |
| | | {{ scope.row.isReverted ? 'å·²æ¤é' : 'ææ' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="120" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | v-if="!scope.row.isReverted" |
| | | type="danger" |
| | | size="mini" |
| | | @click="cancelSingleSplit(scope.row.newBarcode)" |
| | | :disabled="hasPicked(scope.row.newBarcode)"> |
| | | åæ¶ |
| | | </el-button> |
| | | <span v-else style="color: #909399;">å·²æ¤é</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- æ¹éæä½åºå --> |
| | | <div style="margin-top: 15px; padding: 10px; background: #f5f7fa; border-radius: 4px;"> |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div> |
| | | <span style="font-size: 14px; color: #606266;"> |
| | | æ¹éæä½: å¯ä»¥åæ¶æ´ä¸ªæå
龿鿩å个æå
è®°å½åæ¶ |
| | | </span> |
| | | <div style="font-size: 12px; color: #909399; margin-top: 5px;"> |
| | | 宿´æå
é¾å
å«ä»æåå§æ¡ç å¼å§çæææå
æä½ |
| | | </div> |
| | | </div> |
| | | <div> |
| | | <el-button |
| | | type="danger" |
| | | @click="cancelWholeSplitChain" |
| | | :disabled="!canCancelWholeChain" |
| | | :loading="revertSplitLoading"> |
| | | åæ¶æ´ä¸ªæå
é¾ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeSplitChainDialog">å
³é</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- æ¹éååºå¼¹çª --> |
| | | <div v-if="showBatchReturnDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>æ¹æ¬¡ååº</h3> |
| | | <h3>æçååº</h3> |
| | | <el-button type="text" @click="closeBatchReturnDialog" class="close-button">Ã</el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="batchReturnForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æ¹æ¬¡ç¼å·"> |
| | | <el-input v-model="batchReturnForm.batchNo" disabled></el-input> |
| | | <el-form-item label="æçç¼å·"> |
| | | <el-input v-model="batchReturnForm.palletCode" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æªæ£éæ°é"> |
| | | <el-input v-model="batchReturnForm.unpickedQuantity" disabled></el-input> |
| | |
| | | name: 'BatchOutboundPicking', |
| | | components: {printView}, |
| | | data() { |
| | | // éªè¯è§åå®ä¹... |
| | | const validateBatchQuantity = (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === '') { |
| | | callback(new Error('请è¾å
¥åé
æ°é')); |
| | | } else if (value <= 0) { |
| | | callback(new Error('åé
æ°éå¿
须大äº0')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | |
| | | const validateOrderDetailId = (rule, value, callback) => { |
| | | if (!value) { |
| | | callback(new Error('è¯·éæ©ç©ææç»')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | |
| | | return { |
| | | scanData: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | | barcode: '', |
| | | batchNo: '' |
| | | barcode: '' |
| | | }, |
| | | currentBatchNo: '', // å½åæ¹æ¬¡å· |
| | | batchList: [], // æ¹æ¬¡å表 |
| | | selectedBatchNo: '', // éä¸çæ¹æ¬¡å· |
| | | batchSummary: {}, // æ¹æ¬¡æ±æ»ä¿¡æ¯ |
| | | unpickedList: [], |
| | | pickedList: [], |
| | | selectedPickedRows: [], |
| | |
| | | palletStatus: 'æªç¥', |
| | | |
| | | // å¼¹çªç¶æ |
| | | showBatchAllocateDialog: false, |
| | | showCustomSplitDialog: false, |
| | | showRevertSplitDialog: false, |
| | | showBatchReturnDialog: false, |
| | | showEmptyPalletDialog: false, |
| | | showSplitChainDialog: false, // æ°å¢ï¼æå
é¾ä¿¡æ¯å¼¹çª |
| | | |
| | | // å è½½ç¶æ |
| | | batchAllocateLoading: false, |
| | | splitLoading: false, |
| | | revertSplitLoading: false, |
| | | batchReturnLoading: false, |
| | | emptypalletOutLoading: false, |
| | | splitChainLoading: false, // æ°å¢ï¼æå
é¾å è½½ç¶æ |
| | | |
| | | // è¡¨åæ°æ® |
| | | batchAllocateForm: { |
| | | orderNo: '', |
| | | orderDetailId: '', |
| | | batchQuantity: 0 |
| | | }, |
| | | allocatableDetails: [], // å¯åé
ç订åæç» |
| | | |
| | | splitForm: { |
| | | orderNo: '', |
| | | batchNo: '', |
| | | palletCode: '', |
| | | originalBarcode: '', |
| | | materielCode: '', |
| | |
| | | |
| | | batchReturnForm: { |
| | | orderNo: '', |
| | | batchNo: '', |
| | | palletCode: '', |
| | | unpickedCount: 0, |
| | | unpickedQuantity: 0 |
| | | }, |
| | |
| | | palletCode: '' |
| | | }, |
| | | |
| | | // æ°å¢ï¼æå
é¾ç¸å
³æ°æ® |
| | | splitChainInfo: { |
| | | originalBarcode: '', |
| | | totalSplitTimes: 0, |
| | | splitChain: [] |
| | | }, |
| | | |
| | | // éªè¯è§å |
| | | batchAllocateFormRules: { |
| | | orderDetailId: [ |
| | | { required: true, validator: validateOrderDetailId, trigger: 'change' } |
| | | splitFormRules: { |
| | | originalBarcode: [ |
| | | { required: true, message: '请è¾å
¥åæ¡ç ', trigger: 'blur' } |
| | | ], |
| | | batchQuantity: [ |
| | | { required: true, validator: validateBatchQuantity, trigger: 'blur' } |
| | | splitQuantity: [ |
| | | { required: true, message: '请è¾å
¥æå
æ°é', trigger: 'blur' }, |
| | | { type: 'number', min: 0.01, message: 'æå
æ°éå¿
须大äº0', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | // å
¶ä»éªè¯è§å... |
| | | revertSplitFormRules: { |
| | | newBarcode: [ |
| | | { required: true, message: '请è¾å
¥æ°æ¡ç ', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | emptypalletOutFormRules: { |
| | | palletCode: [ |
| | | { required: true, message: '请è¾å
¥æçç ', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | |
| | | isProcessing: false |
| | | } |
| | | }, |
| | | computed: { |
| | | // æ¯å¦å¯ä»¥åæ¶æ´ä¸ªæå
é¾ |
| | | canCancelWholeChain() { |
| | | return this.splitChainInfo.splitChain && |
| | | this.splitChainInfo.splitChain.some(item => !item.isReverted); |
| | | } |
| | | }, |
| | | mounted() { |
| | | if (this.$route.query.orderNo) { |
| | | this.scanData.orderNo = this.$route.query.orderNo; |
| | | this.batchAllocateForm.orderNo = this.$route.query.orderNo; |
| | | this.loadBatchList(); |
| | | this.splitForm.orderNo = this.$route.query.orderNo; |
| | | this.batchReturnForm.orderNo = this.$route.query.orderNo; |
| | | this.emptypalletOutForm.orderNo = this.$route.query.orderNo; |
| | | } |
| | | this.$nextTick(() => { |
| | | this.$refs.palletInput.focus(); |
| | |
| | | methods: { |
| | | goBack(){ |
| | | this.$router.back() |
| | | }, |
| | | |
| | | // æ¹æ¬¡ç¸å
³æ¹æ³ |
| | | async loadBatchList() { |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/order-batch-list', { |
| | | orderNo: this.scanData.orderNo |
| | | }); |
| | | if (res.status) { |
| | | this.batchList = res.data || []; |
| | | if (this.batchList.length > 0) { |
| | | this.selectedBatchNo = this.batchList[0].batchNo; |
| | | this.currentBatchNo = this.selectedBatchNo; |
| | | this.scanData.batchNo = this.selectedBatchNo; |
| | | this.loadBatchData(); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å è½½æ¹æ¬¡å表失败'); |
| | | } |
| | | }, |
| | | |
| | | async refreshBatchList() { |
| | | await this.loadBatchList(); |
| | | this.$message.success('æ¹æ¬¡åè¡¨å·²å·æ°'); |
| | | }, |
| | | |
| | | onBatchChange(batchNo) { |
| | | this.currentBatchNo = batchNo; |
| | | this.scanData.batchNo = batchNo; |
| | | this.loadBatchData(); |
| | | }, |
| | | |
| | | async loadBatchData() { |
| | | if (!this.currentBatchNo) return; |
| | | |
| | | await this.loadBatchSummary(); |
| | | await this.loadUnpickedList(); |
| | | await this.loadPickedList(); |
| | | }, |
| | | |
| | | async loadBatchSummary() { |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/batch-summary', { |
| | | orderNo: this.scanData.orderNo, |
| | | batchNo: this.currentBatchNo |
| | | }); |
| | | if (res.status) { |
| | | this.batchSummary = res.data || {}; |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å è½½æ¹æ¬¡æ±æ»å¤±è´¥'); |
| | | } |
| | | }, |
| | | |
| | | async loadUnpickedList() { |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/batch-unpicked-list', { |
| | | orderNo: this.scanData.orderNo, |
| | | batchNo: this.currentBatchNo |
| | | }); |
| | | this.unpickedList = res.data || []; |
| | | this.summary.unpickedCount = this.unpickedList.length; |
| | | this.summary.unpickedQuantity = this.unpickedList.reduce((sum, item) => sum + (item.remainQuantity || 0), 0); |
| | | } catch (error) { |
| | | this.$message.error('å è½½æªæ£éå表失败'); |
| | | } |
| | | }, |
| | | |
| | | async loadPickedList() { |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/batch-picked-list', { |
| | | orderNo: this.scanData.orderNo, |
| | | batchNo: this.currentBatchNo |
| | | }); |
| | | this.pickedList = res.data || []; |
| | | this.summary.pickedCount = this.pickedList.length; |
| | | } catch (error) { |
| | | this.$message.error('å 载已æ£éå表失败'); |
| | | } |
| | | }, |
| | | |
| | | getBatchStatusType(status) { |
| | | const statusMap = { |
| | | 0: 'info', // åé
ä¸ |
| | | 1: 'warning', // æ§è¡ä¸ |
| | | 2: 'success', // 已宿 |
| | | 3: 'danger' // å·²ååº |
| | | }; |
| | | return statusMap[status] || 'info'; |
| | | }, |
| | | |
| | | // åæ¹åé
ç¸å
³æ¹æ³ |
| | | async openBatchAllocateDialog() { |
| | | this.showBatchAllocateDialog = true; |
| | | await this.loadAllocatableDetails(); |
| | | this.batchAllocateForm.orderDetailId = ''; |
| | | this.batchAllocateForm.batchQuantity = 0; |
| | | }, |
| | | |
| | | async loadAllocatableDetails() { |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/allocatable-order-details', { |
| | | orderNo: this.scanData.orderNo |
| | | }); |
| | | if (res.status) { |
| | | this.allocatableDetails = res.data || []; |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å è½½å¯åé
æç»å¤±è´¥'); |
| | | } |
| | | }, |
| | | |
| | | getAvailableQuantity() { |
| | | const detail = this.allocatableDetails.find(d => d.id === this.batchAllocateForm.orderDetailId); |
| | | return detail ? detail.availableQuantity : 0; |
| | | }, |
| | | |
| | | async handleBatchAllocate() { |
| | | if (this.$refs.batchAllocateFormRef) { |
| | | this.$refs.batchAllocateFormRef.validate(async (valid) => { |
| | | if (valid) { |
| | | this.batchAllocateLoading = true; |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/batch-allocate-stock', this.batchAllocateForm); |
| | | if (res.status) { |
| | | this.$message.success('åæ¹åé
æå'); |
| | | this.showBatchAllocateDialog = false; |
| | | await this.loadBatchList(); // å·æ°æ¹æ¬¡å表 |
| | | } else { |
| | | this.$message.error(res.message || 'åæ¹åé
失败'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('åæ¹åé
失败'); |
| | | } finally { |
| | | this.batchAllocateLoading = false; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | closeBatchAllocateDialog() { |
| | | this.showBatchAllocateDialog = false; |
| | | }, |
| | | |
| | | // 忣ç¸å
³æ¹æ³ |
| | |
| | | return; |
| | | } |
| | | |
| | | if (!this.currentBatchNo) { |
| | | this.$message.warning('请å
éæ©æ¹æ¬¡'); |
| | | return; |
| | | } |
| | | |
| | | this.isProcessing = true; |
| | | |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/confirm-picking', this.scanData); |
| | | const res = await http.post('/api/OutboundBatchPicking/confirm-picking', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | barcode: this.scanData.barcode |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æ£é确认æå'); |
| | | this.scanData.barcode = ''; |
| | | await this.loadBatchData(); |
| | | if(res.data && res.data.splitResults && res.data.splitResults.length>0){ |
| | | this.$refs.childs.open(res.data.splitResults); |
| | | await this.loadPalletData(); |
| | | if(res.data && res.data && res.data.length>0){ |
| | | this.$refs.childs.open(res.data); |
| | | } |
| | | this.$nextTick(() => { |
| | | this.$refs.barcodeInput.focus(); |
| | |
| | | this.$message.warning('请å
æ«ææçç '); |
| | | return; |
| | | } |
| | | if (!this.currentBatchNo) { |
| | | this.$message.warning('请å
éæ©æ¹æ¬¡'); |
| | | return; |
| | | } |
| | | this.showCustomSplitDialog = true; |
| | | this.resetSplitForm(); |
| | | this.splitForm.orderNo = this.scanData.orderNo; |
| | | this.splitForm.batchNo = this.currentBatchNo; |
| | | this.splitForm.palletCode = this.scanData.palletCode; |
| | | }, |
| | | |
| | |
| | | this.splitForm.originalBarcode = this.splitForm.originalBarcode.replace(/\n/g, '').trim(); |
| | | |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/split-package-info', { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package-info', { |
| | | orderNo: this.splitForm.orderNo, |
| | | batchNo: this.splitForm.batchNo, |
| | | palletCode: this.splitForm.palletCode, |
| | | barcode: this.splitForm.originalBarcode |
| | | }); |
| | | |
| | |
| | | if (valid) { |
| | | this.splitLoading = true; |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/manual-split-package', this.splitForm); |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package', { |
| | | orderNo: this.splitForm.orderNo, |
| | | palletCode: this.splitForm.palletCode, |
| | | originalBarcode: this.splitForm.originalBarcode, |
| | | splitQuantity: this.splitForm.splitQuantity |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æå
æå'); |
| | | this.showCustomSplitDialog = false; |
| | | await this.loadBatchData(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'æå
失败'); |
| | | } |
| | |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | // 卿å
å¼¹çªä¸æ¥çæå
é¾ |
| | | async viewSplitChainFromSplit(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | // å
å
³éæå
å¼¹çª |
| | | this.closeCustomSplitDialog(); |
| | | |
| | | await this.$nextTick(); |
| | | |
| | | // ç¶åæå¼æå
é¾ä¿¡æ¯å¼¹çª |
| | | await this.viewSplitChain(barcode); |
| | | }, |
| | | // æ¤éæå
|
| | | async onRevertSplitBarcodeScan() { |
| | | if (!this.revertSplitForm.newBarcode) return; |
| | | this.revertSplitForm.newBarcode = this.revertSplitForm.newBarcode.replace(/\n/g, '').trim(); |
| | | |
| | | // æ°å¢ï¼æ«æåèªå¨æ¾ç¤ºæå
é¾ä¿¡æ¯ |
| | | await this.viewSplitChain(this.revertSplitForm.newBarcode); |
| | | }, |
| | | |
| | | async handleRevertSplit() { |
| | |
| | | if (valid) { |
| | | this.revertSplitLoading = true; |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/cancel-split-package', { |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-split', { |
| | | orderNo: this.scanData.orderNo, |
| | | batchNo: this.currentBatchNo, |
| | | palletCode: this.scanData.palletCode, |
| | | newBarcode: this.revertSplitForm.newBarcode |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æ¤éæå
æå'); |
| | | this.showRevertSplitDialog = false; |
| | | await this.loadBatchData(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'æ¤éæå
失败'); |
| | | } |
| | |
| | | }); |
| | | } |
| | | }, |
| | | // æ¥æ¾å®æ´æå
é¾ï¼ä»æ ¹æ¡ç å¼å§ï¼ |
| | | async findRootChain(currentBarcode) { |
| | | this.splitChainLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/find-root-split-chain', { |
| | | orderNo: this.scanData.orderNo, |
| | | barcode: currentBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitChainInfo = res.data; |
| | | this.$message.success('å·²å è½½å®æ´æå
é¾'); |
| | | } else { |
| | | this.$message.error(res.message || 'æ¥æ¾å®æ´æå
é¾å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ¥æ¾å®æ´æå
é¾å¤±è´¥'); |
| | | } finally { |
| | | this.splitChainLoading = false; |
| | | } |
| | | }, |
| | | // æå
é¾ç¸å
³æ¹æ³ |
| | | // æ¥çæå
é¾ä¿¡æ¯ |
| | | async viewSplitChain(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | this.splitChainLoading = true; |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package-chain-info', { |
| | | orderNo: this.scanData.orderNo, |
| | | barcode: barcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitChainInfo = res.data; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ï¼åè¯ç¨æ·è¿æ¯ä»ä¹ç±»åçæå
é¾ |
| | | let chainType = "å½åæ¡ç çæå
é¾"; |
| | | if (this.splitChainInfo.chainType === 'root') { |
| | | chainType = "宿´æå
é¾ï¼ä»åå§æ¡ç å¼å§ï¼"; |
| | | } else if (this.splitChainInfo.chainType === 'branch') { |
| | | chainType = "忝æå
é¾"; |
| | | } |
| | | |
| | | this.$message.info(`å·²å è½½${chainType}ï¼å
±${this.splitChainInfo.totalSplitTimes}次æå
`); |
| | | this.showSplitChainDialog = true; |
| | | } else { |
| | | this.$message.error(res.message || 'è·åæå
é¾ä¿¡æ¯å¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('è·åæå
é¾ä¿¡æ¯å¤±è´¥'); |
| | | } finally { |
| | | this.splitChainLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // å
³éæå
é¾ä¿¡æ¯å¼¹çª |
| | | closeSplitChainDialog() { |
| | | this.showSplitChainDialog = false; |
| | | |
| | | }, |
| | | // 卿¤éæå
å¼¹çªä¸æ¥çæå
é¾ |
| | | async viewSplitChainFromRevert(barcode) { |
| | | if (!barcode) { |
| | | this.$message.warning('请å
è¾å
¥æ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | // å
å
³éæ¤éæå
å¼¹çª |
| | | this.closeRevertSplitDialog(); |
| | | |
| | | await this.$nextTick(); |
| | | |
| | | // ç¶åæå¼æå
é¾ä¿¡æ¯å¼¹çª |
| | | await this.viewSplitChain(barcode); |
| | | }, |
| | | // å¿«ééæ°æå¼æå
é¾å¼¹çª |
| | | async quickReopenSplitChainDialog(barcode) { |
| | | if (!barcode) return; |
| | | |
| | | this.showSplitChainDialog = true; |
| | | this.splitChainLoading = true; |
| | | |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/split-package-chain-info', { |
| | | orderNo: this.scanData.orderNo, |
| | | barcode: barcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitChainInfo = res.data; |
| | | } |
| | | } catch (error) { |
| | | console.error('éæ°å è½½æå
é¾ä¿¡æ¯å¤±è´¥:', error); |
| | | } finally { |
| | | this.splitChainLoading = false; |
| | | } |
| | | }, |
| | | // åæ¶å个æå
è®°å½ |
| | | async cancelSingleSplit(newBarcode) { |
| | | // å
è®°å½å½åä¿¡æ¯ï¼ç¶åå
³éå¼¹çª |
| | | const originalBarcode = this.splitChainInfo.originalBarcode; |
| | | this.closeSplitChainDialog(); |
| | | |
| | | await this.$nextTick(); |
| | | |
| | | try { |
| | | await this.$confirm( |
| | | `ç¡®å®è¦åæ¶æ¡ç ${newBarcode} çæå
æä½åï¼`, |
| | | 'åæ¶å个æå
', |
| | | { |
| | | confirmButtonText: 'ç¡®å®åæ¶', |
| | | cancelButtonText: 'åæ³æ³', |
| | | type: 'warning' |
| | | } |
| | | ); |
| | | |
| | | this.revertSplitLoading = true; |
| | | |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-split', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | newBarcode: newBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('åæ¶æå
æå'); |
| | | await this.loadPalletData(); |
| | | // éæ°æå¼å¼¹çªæ¾ç¤ºæ´æ°åçç¶æ |
| | | await this.viewSplitChain(originalBarcode); |
| | | } else { |
| | | this.$message.error(res.message || 'åæ¶æå
失败'); |
| | | await this.viewSplitChain(originalBarcode); |
| | | } |
| | | } catch (error) { |
| | | if (error === 'cancel') { |
| | | // ç¨æ·åæ¶åéæ°æå¼å¼¹çª |
| | | await this.viewSplitChain(originalBarcode); |
| | | } else { |
| | | this.$message.error('åæ¶æå
失败'); |
| | | await this.viewSplitChain(originalBarcode); |
| | | } |
| | | } finally { |
| | | this.revertSplitLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // åæ¶æ´ä¸ªæå
é¾ |
| | | async cancelWholeSplitChain() { |
| | | // å
è®°å½å½åæå
é¾ä¿¡æ¯ï¼ç¶åå
³éå¼¹çª |
| | | const originalBarcode = this.splitChainInfo.originalBarcode; |
| | | this.closeSplitChainDialog(); |
| | | |
| | | // ç»ä¸ç¹æ¶é´è®©å¼¹çªå®å
¨å
³é |
| | | await this.$nextTick(); |
| | | |
| | | try { |
| | | // ç°å¨æ¾ç¤ºç¡®è®¤å¯¹è¯æ¡ï¼ç¡®ä¿å®å¨æåé¢ |
| | | await this.$confirm( |
| | | `ç¡®å®è¦åæ¶æ´ä¸ªæå
é¾åï¼\nè¿å°åæ¶ä»æ¡ç ${originalBarcode} å¼å§çæææå
æä½ã`, |
| | | 'åæ¶æå
é¾ç¡®è®¤', |
| | | { |
| | | confirmButtonText: 'ç¡®å®åæ¶', |
| | | cancelButtonText: 'åæ³æ³', |
| | | type: 'warning', |
| | | center: true, |
| | | closeOnClickModal: false |
| | | } |
| | | ); |
| | | |
| | | // ç¨æ·ç¡®è®¤åæ§è¡åæ¶æä½ |
| | | this.revertSplitLoading = true; |
| | | |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-split-chain', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | startBarcode: originalBarcode |
| | | }); |
| | | |
| | | console.log('åæ¶æå
é¾ååº:', res); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('åæ¶æå
龿å'); |
| | | await this.loadPalletData(); |
| | | // å¯éï¼éæ°æå¼æå
é¾ä¿¡æ¯å¼¹çªæ¾ç¤ºæ´æ°åçç¶æ |
| | | // await this.viewSplitChain(originalBarcode); |
| | | } else { |
| | | this.$message.error(res.message || 'åæ¶æå
é¾å¤±è´¥'); |
| | | // 失败åéæ°æå¼å¼¹çª |
| | | await this.viewSplitChain(originalBarcode); |
| | | } |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶æä½ |
| | | if (error === 'cancel') { |
| | | console.log('ç¨æ·åæ¶äºæå
龿ä½'); |
| | | // ç¨æ·åæ¶åéæ°æå¼å¼¹çª |
| | | await this.viewSplitChain(originalBarcode); |
| | | } else { |
| | | console.error('åæ¶æå
é¾é误:', error); |
| | | this.$message.error('åæ¶æå
é¾å¤±è´¥: ' + error.message); |
| | | // åºéåéæ°æå¼å¼¹çª |
| | | await this.viewSplitChain(originalBarcode); |
| | | } |
| | | } finally { |
| | | this.revertSplitLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // æ£æ¥æ¡ç æ¯å¦å·²è¢«åæ£ |
| | | hasPicked(barcode) { |
| | | return this.pickedList.some(item => item.currentBarcode === barcode); |
| | | }, |
| | | |
| | | // æ ¼å¼åæ¥ææ¶é´ |
| | | formatDateTime(dateTime) { |
| | | if (!dateTime) return ''; |
| | | const date = new Date(dateTime); |
| | | return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}`; |
| | | }, |
| | | |
| | | // ååºç¸å
³æ¹æ³ |
| | | openBatchReturnDialog() { |
| | | if (!this.currentBatchNo) { |
| | | this.$message.warning('请å
éæ©æ¹æ¬¡'); |
| | | if (!this.scanData.palletCode) { |
| | | this.$message.warning('请å
æ«ææçç '); |
| | | return; |
| | | } |
| | | this.showBatchReturnDialog = true; |
| | | this.batchReturnForm.orderNo = this.scanData.orderNo; |
| | | this.batchReturnForm.batchNo = this.currentBatchNo; |
| | | this.batchReturnForm.palletCode = this.scanData.palletCode; |
| | | this.batchReturnForm.unpickedCount = this.summary.unpickedCount; |
| | | this.batchReturnForm.unpickedQuantity = this.summary.unpickedQuantity; |
| | | }, |
| | |
| | | async handleBatchReturnConfirm() { |
| | | this.batchReturnLoading = true; |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/batch-return-stock', { |
| | | const res = await http.post('/api/OutboundBatchPicking/return-stock', { |
| | | orderNo: this.scanData.orderNo, |
| | | batchNo: this.currentBatchNo |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('æ¹æ¬¡ååºæå'); |
| | | this.$message.success('ååºæå'); |
| | | this.showBatchReturnDialog = false; |
| | | await this.loadBatchData(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'æ¹æ¬¡ååºå¤±è´¥'); |
| | | this.$message.error(res.message || 'ååºå¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ¹æ¬¡ååºå¤±è´¥'); |
| | | this.$message.error('ååºå¤±è´¥'); |
| | | } finally { |
| | | this.batchReturnLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // åç©ºç®±æ¹æ³ |
| | | handleEmptyPallet() { |
| | | this.showEmptyPalletDialog = true; |
| | | this.emptypalletOutForm.orderNo = this.scanData.orderNo; |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | }, |
| | | |
| | | async handleEmptyPalletConfirm() { |
| | | this.emptypalletOutLoading = true; |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/remove-empty-pallet', this.emptypalletOutForm); |
| | | const res = await http.post('/api/OutboundBatchPicking/remove-empty-pallet', { |
| | | orderNo: this.emptypalletOutForm.orderNo, |
| | | palletCode: this.emptypalletOutForm.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.$message.success('å走空箱æå'); |
| | | this.showEmptyPalletDialog = false; |
| | | await this.loadBatchData(); |
| | | await this.loadPalletData(); |
| | | } else { |
| | | this.$message.error(res.message || 'å走空箱失败'); |
| | | } |
| | |
| | | } |
| | | }, |
| | | |
| | | // å
¶ä»åææ¹æ³... |
| | | // æ°æ®å è½½æ¹æ³ |
| | | async loadPalletData() { |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode) return; |
| | | |
| | | await this.loadUnpickedList(); |
| | | await this.loadPickedList(); |
| | | await this.loadPalletStatus(); |
| | | }, |
| | | |
| | | async loadUnpickedList() { |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/pallet-locks', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | //this.unpickedList = res.data || []; |
| | | this.unpickedList = (res.data || []).filter(item => item.canPick === true); |
| | | this.summary.unpickedCount = this.unpickedList.length; |
| | | this.summary.unpickedQuantity = this.unpickedList.reduce((sum, item) => sum + (item.remainQuantity || 0), 0); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å è½½æªæ£éå表失败'); |
| | | } |
| | | }, |
| | | |
| | | async loadPickedList() { |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/pallet-picked-list', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.pickedList = res.data || []; |
| | | |
| | | this.pickedList = res.data.map(item => { |
| | | // æ¹å¼1ï¼ä¿çåbarcodeåæ®µï¼æ°å¢currentBarcode |
| | | return { |
| | | ...item, |
| | | currentBarcode: item.barcode |
| | | }; |
| | | }); |
| | | |
| | | this.summary.pickedCount = this.pickedList.length; |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å 载已æ£éå表失败'); |
| | | } |
| | | }, |
| | | |
| | | async loadPalletStatus() { |
| | | try { |
| | | const res = await http.post('/api/OutboundBatchPicking/pallet-status', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status) { |
| | | this.palletStatus = res.data.statusText || 'æªç¥'; |
| | | } |
| | | } catch (error) { |
| | | this.palletStatus = 'æªç¥'; |
| | | } |
| | | }, |
| | | |
| | | // æ«ç ç¸å
³æ¹æ³ |
| | | onPalletScan() { |
| | | this.scanData.palletCode = this.scanData.palletCode.replace(/\n/g, '').trim(); |
| | | if (!this.scanData.palletCode) return; |
| | | |
| | | this.loadActiveBatch(); |
| | | this.loadPalletData(); |
| | | this.$nextTick(() => { |
| | | this.$refs.barcodeInput.focus(); |
| | | }); |
| | | }, |
| | | |
| | | async loadActiveBatch() { |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/active-batch', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | if (res.status && res.data) { |
| | | this.currentBatchNo = res.data.batchNo; |
| | | this.scanData.batchNo = res.data.batchNo; |
| | | this.selectedBatchNo = res.data.batchNo; |
| | | await this.loadBatchData(); |
| | | } |
| | | } catch (error) { |
| | | console.log('è·åæ´»è·æ¹æ¬¡å¤±è´¥ï¼å¯è½æç没æå
³èæ¹æ¬¡'); |
| | | } |
| | | }, |
| | | |
| | | onBarcodeScan() { |
| | |
| | | try { |
| | | for (const row of this.selectedPickedRows) { |
| | | try { |
| | | const res = await http.post('/api/BatchOutbound/cancel-picking', { |
| | | const res = await http.post('/api/OutboundBatchPicking/cancel-picking', { |
| | | orderNo: this.scanData.orderNo, |
| | | batchNo: this.currentBatchNo, |
| | | palletCode: this.scanData.palletCode, |
| | | barcode: row.currentBarcode |
| | | }); |
| | |
| | | } |
| | | } |
| | | this.$message.success('æ¹é忶宿'); |
| | | await this.loadBatchData(); |
| | | await this.loadPalletData(); |
| | | this.selectedPickedRows = []; |
| | | } catch (error) { |
| | | this.$message.error('æ¹éåæ¶æä½å¤±è´¥'); |
| | |
| | | this.showBatchReturnDialog = false; |
| | | }, |
| | | |
| | | openEmptyPalletDialog() { |
| | | this.showEmptyPalletDialog = true; |
| | | this.emptypalletOutForm.orderNo = this.scanData.orderNo; |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | onEmptyPalletScan() { |
| | | if (!this.emptypalletOutForm.palletCode) return; |
| | | this.emptypalletOutForm.palletCode = this.emptypalletOutForm.palletCode.replace(/\n/g, '').trim(); |
| | | }, |
| | | |
| | | closeEmptyPalletDialog() { |
| | |
| | | this.emptypalletOutForm.palletCode = ''; |
| | | }, |
| | | |
| | | onEmptyPalletScan() { |
| | | if (!this.emptypalletOutForm.palletCode) return; |
| | | this.emptypalletOutForm.palletCode = this.emptypalletOutForm.palletCode.replace(/\n/g, '').trim(); |
| | | parentcall() { |
| | | // æå°åè° |
| | | } |
| | | } |
| | | }) |
| | |
| | | <style scoped> |
| | | .OutboundPicking-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .batch-operations { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .batch-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .batch-summary-area { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .batch-summary-info { |
| | | display: flex; |
| | | gap: 15px; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .scanner-form { |
| | |
| | | } |
| | | |
| | | /* èªå®ä¹å¼¹çªæ ·å¼ */ |
| | | :deep(.el-message-box) { |
| | | z-index: 10010 !important; |
| | | } |
| | | |
| | | :deep(.el-overlay) { |
| | | z-index: 10009 !important; |
| | | } |
| | | |
| | | :deep(.el-message) { |
| | | z-index: 10011 !important; |
| | | } |
| | | |
| | | .custom-dialog-overlay { |
| | | position: fixed; |
| | | top: 0; |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 9999; |
| | | z-index: 2000; /* ä¿æä¸ä¸ªåçç z-index */ |
| | | } |
| | | |
| | | .custom-dialog-wrapper { |
| | | position: relative; |
| | | z-index: 10000; |
| | | z-index: 2001; |
| | | } |
| | | |
| | | .custom-dialog { |
| | |
| | | flex-direction: column; |
| | | align-items: stretch; |
| | | } |
| | | |
| | | /* ç¡®ä¿ç¡®è®¤å¯¹è¯æ¡å¨æåé¢ */ |
| | | .el-message-box__wrapper { |
| | | z-index: 10001 !important; |
| | | } |
| | | |
| | | .el-message { |
| | | z-index: 10002 !important; |
| | | } |
| | | .scanner-form .el-input { |
| | | width: 100%; |
| | | } |