| | |
| | | <i class="el-icon-document"></i> |
| | | <span class="order-label">订åå·ï¼</span> |
| | | <span class="order-value">{{ orderNo }}</span> |
| | | <span class="order-label" style="margin-left: 20px;">产线åç§°ï¼</span> |
| | | <span class="order-value">{{ orderInfo?.departmentName || '' }}</span> |
| | | </div> |
| | | <div class="order-status"> |
| | | <!-- æµè¯æé® --> |
| | | |
| | | <el-tag v-if="orderInfo" :type="getStatusType(orderInfo.orderStatus)" size="medium" |
| | | style="margin-left: 10px;"> |
| | | {{ orderInfo.statusName || 'è¿è¡ä¸' }} |
| | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="æçç " prop="palletCode"> |
| | | <el-input ref="palletInput" v-model="scanForm.palletCode" placeholder="è¯·æ«ææçç " |
| | | size="large" clearable @keyup.enter="handlePalletScan"> |
| | | <el-input ref="palletInput" v-model="scanForm.palletCode" placeholder="è¯·æ«ææçç " size="large" |
| | | clearable @keyup.enter="handlePalletScan"> |
| | | <template #prefix> |
| | | <i class="el-icon-box"></i> |
| | | </template> |
| | |
| | | </el-table-column> |
| | | <el-table-column prop="unit" label="åä½" width="60" /> |
| | | <el-table-column prop="locationCode" label="åºä½" /> |
| | | <!-- <el-table-column label="æä½" width="80" align="center"> |
| | | <template #default="scope"> |
| | | <el-button type="text" size="small" @click="quickPick(scope.row)" |
| | | :disabled="!scanForm.palletCode"> |
| | | æ£é |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> --> |
| | | </el-table> |
| | | |
| | | <div class="table-footer"> |
| | |
| | | <el-table-column prop="createDate" label="æ£éæ¶é´" width="160" /> |
| | | <el-table-column prop="originalBarcode" label="åç©æç " width="160" /> |
| | | <el-table-column prop="newBarcode" label="æ°ç©æç " width="160" /> |
| | | <!-- <el-table-column label="æä½" width="80" align="center"> |
| | | <template #default="scope"> |
| | | <el-button type="text" size="small" @click="undoPick(scope.row)"> |
| | | æ¤é |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> --> |
| | | </el-table> |
| | | |
| | | <div class="table-footer"> |
| | |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- æçç©æåºåä¿¡æ¯ --> |
| | | <!-- <div class="pallet-inventory" v-if="scanForm.palletCode && unpickedData.length > 0"> |
| | | <el-divider content-position="left"> |
| | | <span style="color: #67C23A; font-size: 14px;"> |
| | | <i class="el-icon-goods"></i> æçç©æåºåä¿¡æ¯ |
| | | </span> |
| | | </el-divider> |
| | | <div class="inventory-container"> |
| | | <el-table :data="unpickedData" size="small" :show-header="true" :border="true" stripe |
| | | highlight-current-row max-height="200" class="inventory-table"> |
| | | <el-table-column type="index" label="åºå·" width="50" align="center" /> |
| | | <el-table-column prop="materielCode" label="ç©æç¼ç " width="100" show-overflow-tooltip /> |
| | | <el-table-column prop="materielName" label="ç©æåç§°" width="120" show-overflow-tooltip /> |
| | | <el-table-column prop="batchNo" label="æ¹æ¬¡å·" width="90" /> |
| | | <el-table-column label="å½ååºå" width="80" align="right"> |
| | | <template #default="scope"> |
| | | <el-text type="primary" tag="b">{{ scope.row.currentStock || 0 }}</el-text> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="忣æ°é" width="80" align="right"> |
| | | <template #default="scope"> |
| | | <el-text type="warning">{{ scope.row.assignQuantity }}</el-text> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="已忣" width="70" align="right"> |
| | | <template #default="scope"> |
| | | <el-text type="success">{{ scope.row.sortedQuantity || 0 }}</el-text> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å©ä½åºå" width="80" align="right"> |
| | | <template #default="scope"> |
| | | <el-text type="info">{{ calculateRemainingStock(scope.row) }}</el-text> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="unit" label="åä½" width="100" align="center" /> |
| | | <el-table-column prop="locationCode" label="åºä½" width="150" /> |
| | | <el-table-column label="ç¶æ" width="80" align="center"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStockStatusType(scope.row)" size="mini"> |
| | | {{ getStockStatusText(scope.row) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> --> |
| | | </div> |
| | | |
| | | <print-view ref="printView" @parentcall="parentcall"></print-view> |
| | |
| | | </el-dialog> |
| | | |
| | | <!-- æ´åºç¡®è®¤å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="wholeOutDialogVisible" title="æ´åºæä½ç¡®è®¤" width="500px" |
| | | :before-close="handleWholeOutDialogClose" custom-class="whole-out-dialog" style="margin-right: 0px;"> |
| | | <el-dialog v-model="wholeOutDialogVisible" title="æ´åºæä½ç¡®è®¤" width="500px" :before-close="handleWholeOutDialogClose" |
| | | custom-class="whole-out-dialog" style="margin-right: 0px;"> |
| | | <div class="whole-out-content" v-if="wholeOutInfo"> |
| | | <!-- è¦åæç¤º --> |
| | | <el-alert title="该æçå
å«éè¦æ´åºçç©æ" type="warning" :closable="false" show-icon class="whole-out-alert"> |
| | |
| | | <div class="info-item"> |
| | | <label>æ´åºæ°éï¼</label> |
| | | <span class="info-value highlight">{{ wholeOutInfo.assignQuantity }} {{ wholeOutInfo.unit |
| | | }}</span> |
| | | }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <label>å½ååºåï¼</label> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import printView from "@/extension/outbound/extend/printView.vue" |
| | | import { stationManager, STATION_STORAGE_KEY } from "@/../src/uitils/stationManager"; |
| | | import { ElLoading } from 'element-plus' |
| | | |
| | | // 导å
¥é³é¢æä»¶ï¼éé
src/assetsç®å½ï¼webpackèªå¨å¤çï¼ |
| | | const successAudioSrc = require('@/assets/audio/success.mp3'); |
| | | const errorAudioSrc = require('@/assets/audio/error.mp3'); |
| | | |
| | | export default { |
| | | components: { printView }, |
| | |
| | | wholeOutDialogVisible: false, |
| | | wholeOutInfo: null, |
| | | globalLoading: false, |
| | | loadingInstance: null |
| | | loadingInstance: null, |
| | | // é³é¢å®ä¾ï¼ç¼åï¼é¿å
éå¤åå»ºï¼ |
| | | successAudio: null, |
| | | errorAudio: null |
| | | } |
| | | }, |
| | | computed: { |
| | |
| | | }, |
| | | mounted() { |
| | | this.initPage() |
| | | // åå§åé³é¢å®ä¾ï¼æå è½½ï¼ä»
åå»ºä¸æ¬¡ï¼ |
| | | this.initAudioInstance() |
| | | }, |
| | | beforeDestroy() { |
| | | // 鿝é³é¢å®ä¾ï¼éæ¾èµæº |
| | | this.successAudio = null |
| | | this.errorAudio = null |
| | | }, |
| | | methods: { |
| | | // åå§åé³é¢å®ä¾ï¼æ ¸å¿ï¼éé
src/assetsè·¯å¾ï¼ç¼åå®ä¾ï¼ |
| | | initAudioInstance() { |
| | | // æåé³é¢å®ä¾ |
| | | if (!this.successAudio) { |
| | | this.successAudio = new Audio(successAudioSrc) |
| | | this.successAudio.onerror = (err) => { |
| | | console.error('ãæåé³é¢ãå 载失败', err) |
| | | } |
| | | } |
| | | if (!this.errorAudio) { |
| | | this.errorAudio = new Audio(errorAudioSrc) |
| | | this.errorAudio.onerror = (err) => { |
| | | console.error('ãé误é³é¢ãå 载失败', err) |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // ============== æ°å¢ï¼æ ¹æ®æçå·è·å订åå·ï¼æ ¸å¿åè½ï¼ ============== |
| | | async getOrderNoByPallet(palletCode) { |
| | | if (!palletCode) { |
| | | this.$message.warning('æçå·ä¸è½ä¸ºç©º'); |
| | | return null; |
| | | } |
| | | |
| | | try { |
| | | this.showFullScreenLoading(); |
| | | // è°ç¨è·å订åå·çæ¥å£ |
| | | const response = await this.http.get(`/api/OutboundOrder/GetOrderNoByPalletCode?palletCode=${palletCode}`); |
| | | |
| | | if (response.status && response.data) { |
| | | const validOrderNo = response.data; |
| | | this.playSuccessAudio(); |
| | | this.$message.success(`æåè·å订åå·ï¼${validOrderNo}`); |
| | | return validOrderNo; |
| | | } else { |
| | | this.playErrorAudio(); |
| | | const errorMsg = response.message || '该æçå·æªå
³èä»»ä½è®¢å'; |
| | | this.$message.error(errorMsg); |
| | | return null; |
| | | } |
| | | } catch (error) { |
| | | this.playErrorAudio(); |
| | | const errorMsg = `è·å订åå·å¼å¸¸ï¼${error.message || 'ç½ç»é误'}`; |
| | | this.$message.error(errorMsg); |
| | | console.error("ãæçå·æ¥è®¢åå·æ¥å£å¼å¸¸ã", error); |
| | | return null; |
| | | } finally { |
| | | this.hideFullScreenLoading(); |
| | | } |
| | | }, |
| | | // ============== æ°å¢ç»æ ============== |
| | | |
| | | // ææ¾æåé³é¢ |
| | | playSuccessAudio() { |
| | | try { |
| | | // éç½®ææ¾è¿åº¦ï¼é¿å
éå¤ææ¾æ¶é³é¢æªç»æï¼ |
| | | this.successAudio.currentTime = 0 |
| | | // ææ¾ï¼å
¼å®¹æµè§å¨èªå¨ææ¾çç¥éå¶ï¼ |
| | | this.successAudio.play().catch((err) => { |
| | | console.warn('æåé³é¢ææ¾å¤±è´¥ï¼æµè§å¨èªå¨ææ¾çç¥éå¶ï¼', err) |
| | | }) |
| | | } catch (err) { |
| | | console.error('ææ¾æåé³é¢å¼å¸¸', err) |
| | | } |
| | | }, |
| | | playErrorAudio() { |
| | | try { |
| | | this.errorAudio.currentTime = 0 |
| | | this.errorAudio.play().catch((err) => { |
| | | console.warn('é误é³é¢ææ¾å¤±è´¥ï¼æµè§å¨èªå¨ææ¾çç¥éå¶ï¼', err) |
| | | }) |
| | | } catch (err) { |
| | | console.error('ææ¾é误é³é¢å¼å¸¸', err) |
| | | } |
| | | }, |
| | | initPage() { |
| | | // ä»è·¯ç±åæ°è·å订åå· |
| | | this.orderNo = this.$route.query.orderNo || '' |
| | | if (!this.orderNo) { |
| | | this.$message.error('订åå·ä¸è½ä¸ºç©º') |
| | | this.$router.back() |
| | | return |
| | | } |
| | | // ============== å¾®è°ï¼æ³¨é强å¶è¿åé»è¾ï¼å
¼å®¹æçå·æ¥è®¢åå· ============== |
| | | // if (!this.orderNo) { |
| | | // this.$message.error('订åå·ä¸è½ä¸ºç©º') |
| | | // this.$router.back() |
| | | // return |
| | | // } |
| | | // ============== å¾®è°ç»æ ============== |
| | | |
| | | // å 载订åä¿¡æ¯ |
| | | this.loadOrderInfo() |
| | |
| | | } |
| | | }, |
| | | loadUnpickedData() { |
| | | return new Promise((resolve, reject) => { |
| | | this.http.post(`/api/Outbound/QueryPickingTasks?orderNo=${this.orderNo}&palletCode=${this.scanForm.palletCode}`, {}).then(response => { |
| | | if (response.status) { |
| | | if (response.data.outStockLockInfos.length > 0) { |
| | | this.unpickedData = response.data.outStockLockInfos; |
| | | this.matMixed = response.data.isMatMixed; |
| | | this.calculateUnpickedStats() |
| | | // æ£æ¥æ¯å¦éè¦æ´åºç¡®è®¤ |
| | | this.$nextTick(() => { |
| | | if (this.hasWholeOut()) { |
| | | this.showWholeOutConfirm() |
| | | } |
| | | }) |
| | | // èªå¨èç¦å°ç©ææ¡ç è¾å
¥æ¡ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.materialInput) { |
| | | this.$refs.materialInput.focus() |
| | | } |
| | | }) |
| | | } else { |
| | | if (flag) { |
| | | this.$message.warning('该æçæ æªæ£éä»»å¡') |
| | | } |
| | | this.unpickedData = [] |
| | | return new Promise((resolve, reject) => { |
| | | // å
æ¸
空ä¹åçæç¤ºï¼é¿å
éå¤æç¤º |
| | | this.$message.closeAll(); |
| | | |
| | | this.http.post(`/api/Outbound/QueryPickingTasks?orderNo=${this.orderNo}&palletCode=${this.scanForm.palletCode}`, {}).then(response => { |
| | | if (response.status) { |
| | | // æ
åµ1ï¼ææªæ£éæ°æ® |
| | | if (response.data.outStockLockInfos && response.data.outStockLockInfos.length > 0) { |
| | | this.unpickedData = response.data.outStockLockInfos; |
| | | this.matMixed = response.data.isMatMixed; |
| | | this.orderOver = response.data.orderOver; |
| | | this.calculateUnpickedStats() |
| | | |
| | | // æ£æ¥æ´åºç¡®è®¤ |
| | | this.$nextTick(() => { |
| | | if (this.hasWholeOut()) { |
| | | this.showWholeOutConfirm() |
| | | } |
| | | resolve() |
| | | } else { |
| | | this.$message.error(response.message || 'è·åæçæ°æ®å¤±è´¥') |
| | | this.unpickedData = [] |
| | | reject(response.message || 'è·åæçæ°æ®å¤±è´¥') |
| | | } |
| | | }).catch(error => { |
| | | reject(error) |
| | | }) |
| | | }) |
| | | }, |
| | | }) |
| | | |
| | | // èç¦ç©ææ¡ç è¾å
¥æ¡ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.materialInput) { |
| | | this.$refs.materialInput.focus() |
| | | } |
| | | }) |
| | | } |
| | | // æ
åµ2ï¼æ æªæ£éæ°æ® |
| | | else { |
| | | this.unpickedData = []; |
| | | this.calculateUnpickedStats(); // éç½®ç»è®¡æ°æ® |
| | | |
| | | // å好æç¤º + 交äºä¼å |
| | | this.$message.success({ |
| | | message: `æçã${this.scanForm.palletCode}ãå·²æ£éå®æï¼ææ æ£éè®°å½`, |
| | | duration: 3000, // æç¤ºæ¾ç¤º3ç§ |
| | | showClose: true // å
许æå¨å
³é |
| | | }); |
| | | |
| | | // æ¸
ç©ºç©ææ¡ç å¹¶èç¦åæçç è¾å
¥æ¡ |
| | | this.scanForm.materialBarcode = ''; |
| | | this.$nextTick(() => { |
| | | if (this.$refs.palletInput) { |
| | | this.$refs.palletInput.focus(); |
| | | } |
| | | }); |
| | | } |
| | | resolve(); |
| | | } |
| | | // æ
åµ3ï¼æ¥å£è¿å失败 |
| | | else { |
| | | this.unpickedData = []; |
| | | this.calculateUnpickedStats(); |
| | | |
| | | this.$message.error({ |
| | | message: response.message || `è·åæçã${this.scanForm.palletCode}ãæ£éæ°æ®å¤±è´¥`, |
| | | duration: 5000, |
| | | showClose: true |
| | | }); |
| | | reject(response.message || 'è·åæçæ°æ®å¤±è´¥'); |
| | | } |
| | | }).catch(error => { |
| | | // æ
åµ4ï¼ç½ç»/请æ±å¼å¸¸ |
| | | this.unpickedData = []; |
| | | this.calculateUnpickedStats(); |
| | | |
| | | this.$message.error({ |
| | | message: `è·åæçã${this.scanForm.palletCode}ãæ£éæ°æ®å¼å¸¸ï¼${error.message || 'ç½ç»é误ï¼è¯·éè¯'}`, |
| | | duration: 5000, |
| | | showClose: true |
| | | }); |
| | | reject(error); |
| | | }) |
| | | }) |
| | | }, |
| | | |
| | | loadPickedData() { |
| | | return new Promise((resolve, reject) => { |
| | |
| | | this.calculatePickedStats() |
| | | } else { |
| | | this.pickedData = [] |
| | | |
| | | } |
| | | resolve() |
| | | |
| | | } else { |
| | | this.$message.error(response.message || 'è·åæçæ°æ®å¤±è´¥') |
| | | this.pickedData = [] |
| | |
| | | }, |
| | | |
| | | handlePalletScan(flag = true) { |
| | | if (this.scanForm.palletCode) { |
| | | // this.$message.success(`æçç : ${this.scanForm.palletCode}`) |
| | | this.loadPalletData(flag) |
| | | } else { |
| | | const palletCode = this.scanForm.palletCode.trim(); |
| | | if (!palletCode) { |
| | | return; |
| | | } |
| | | // å
æ ¹æ®æçå·è·å订åå· |
| | | this.getOrderNoByPallet(palletCode).then((orderNo) => { |
| | | if (orderNo) { |
| | | // èµå¼è®¢åå·ï¼ä¾åç»é»è¾ä½¿ç¨ |
| | | this.orderNo = orderNo; |
| | | // å·æ°è®¢åä¿¡æ¯ |
| | | this.loadOrderInfo(); |
| | | } |
| | | this.loadPalletData(flag); |
| | | }); |
| | | }, |
| | | |
| | | handleMaterialScan() { |
| | |
| | | this.$refs.printView.open(response.data.scannedDetail.materialCodes); |
| | | } |
| | | this.$message.success('æ£é确认æå') |
| | | // æ¥å£æåï¼ææ¾æåé³é¢ |
| | | this.playSuccessAudio() |
| | | this.resetMaterialBarcode() |
| | | // this.loadUnpickedData() |
| | | // this.loadPickedData() |
| | | await this.loadPalletData(false) |
| | | } else { |
| | | this.$message.error(response.message || 'æ£é确认失败') |
| | | this.playErrorAudio() |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ£é确认失败') |
| | | this.playErrorAudio() |
| | | } finally { |
| | | this.confirmLoading = false |
| | | this.hideFullScreenLoading() |
| | |
| | | this.$message.success('æä½æå') |
| | | this.confirmDialogVisible = false |
| | | this.resetForm() |
| | | // this.loadUnpickedData() |
| | | // this.loadPickedData() |
| | | } else { |
| | | this.$message.error(response.message || 'æä½å¤±è´¥') |
| | | } |
| | |
| | | } |
| | | }, |
| | | |
| | | // handleUnpickedRowClick(row) { |
| | | // // ç¹å»æªæ£éè¡æ¶èªå¨å¡«å
ç©ææ¡ç |
| | | // this.scanForm.materialBarcode = row.materielCode |
| | | // }, |
| | | |
| | | refreshUnpickedTable() { |
| | | if (this.scanForm.palletCode) { |
| | | this.loadPalletData() |
| | |
| | | |
| | | // æ£æ¥æ¯å¦å
嫿´åº |
| | | hasWholeOut() { |
| | | return this.unpickedData.some(item => item.assignQuantity === item.originalQuantity) && !this.matMixed; |
| | | return this.unpickedData.some(item => item.assignQuantity === item.originalQuantity) && !this.matMixed && !this.orderOver |
| | | }, |
| | | |
| | | // 计ç®å©ä½åºå |