| | |
| | | <template> |
| | | <div class="picking-confirm"> |
| | | <div class="OutboundPicking-container"> |
| | | <div class="page-header"> |
| | | <el-page-header @back="goBack"> |
| | | <template #content> |
| | |
| | | </template> |
| | | </el-page-header> |
| | | </div> |
| | | <!-- æ«ç åºå --> |
| | | <div class="scanner-area"> |
| | | <el-card> |
| | | <div class="scanner-form"> |
| | | <el-input |
| | | ref="palletInput" |
| | | v-model="scanData.palletCode" |
| | | placeholder="æ«ææçç " |
| | | @change="onPalletScan" |
| | | @keyup.enter.native="onPalletScan"> |
| | | </el-input> |
| | | <el-input |
| | | ref="barcodeInput" |
| | | v-model="scanData.barcode" |
| | | placeholder="æ«æç©ææ¡ç " |
| | | @change="onBarcodeScan" |
| | | @keyup.enter.native="onBarcodeScan"> |
| | | </el-input> |
| | | <el-button type="success" @click="confirmPicking">确认æ£é</el-button> |
| | | <!-- <el-button type="warning" @click="openSplitDialog">æå
</el-button> |
| | | <el-button type="info" @click="openRevertSplitDialog">æ¤éæå
</el-button> --> |
| | | |
| | | <el-button type="primary" @click="openBatchReturnDialog">ååº</el-button> |
| | | <!-- <el-button type="danger" @click="handleDirectOutbound">ç´æ¥åºåº</el-button> --> |
| | | |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æ±æ»ä¿¡æ¯ --> |
| | | <div class="summary-area"> |
| | | <el-card> |
| | | <div class="summary-info"> |
| | | <el-tag type="warning">æªæ£éæ¡æ°: {{summary.unpickedCount}}</el-tag> |
| | | <el-tag type="danger">æªæ£éæ°é: {{summary.unpickedQuantity}}</el-tag> |
| | | <!-- <el-tag type="success">å·²æ£éæ¡æ°: {{summary.pickedCount}}</el-tag> --> |
| | | <el-tag type="info">æçç¶æ: {{palletStatus}}</el-tag> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <!-- æ°æ®å表 --> |
| | | <div class="content-area"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-card header="æªæ£éå表"> |
| | | <el-table :data="unpickedList" border height="440"> |
| | | <el-table-column prop="materielCode" label="ç©æç¼ç " width="120"></el-table-column> |
| | | |
| | | <div class="content-layout"> |
| | | <!-- å·¦ä¾§ï¼æ«ç åºå --> |
| | | <div class="left-section"> |
| | | <div class="scan-section"> |
| | | <el-alert |
| | | title="è¯·ä½¿ç¨æ«ç æªæ«ææçç åç©ææ¡ç ï¼æ«ç æªå¸¦å车åè½ï¼æ«å®ç©ææ¡ç èªå¨ç¡®è®¤" |
| | | type="info" |
| | | :closable="false" |
| | | class="scan-alert" |
| | | /> |
| | | <el-table-column prop="assignQuantity" label="åé
æ°é" width="100"></el-table-column> |
| | | <el-table-column prop="remainQuantity" 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-column label="æä½" width="100"> |
| | | <template slot-scope="scope"> |
| | | <el-button |
| | | size="mini" |
| | | type="primary" |
| | | @click="handleSingleReturn(scope.row)"> |
| | | ååº |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> --> |
| | | </el-table> |
| | | </el-card> |
| | | </el-col> |
| | | |
| | | <el-col :span="12"> |
| | | <el-card header="å·²æ£éå表"> |
| | | <div class="table-actions"> |
| | | <el-button |
| | | size="mini" |
| | | type="danger" |
| | | :disabled="selectedPickedRows.length === 0" |
| | | @click="batchCancelSelected"> |
| | | åæ¶æ£é |
| | | </el-button> |
| | | <span class="selection-count">已鿩 {{selectedPickedRows.length}} 项</span> |
| | | </div> |
| | | <el-table :data="pickedList" border height="400" style="width: 100%" @selection-change="handlePickedSelectionChange"> |
| | | <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="currentBarcode" label="æ¡ç "></el-table-column> |
| | | |
| | | |
| | | <el-form :model="scanForm" label-width="100px" class="scan-form"> |
| | | <el-form-item label="æçç " required> |
| | | <el-input |
| | | ref="palletInput" |
| | | v-model="scanForm.palletCode" |
| | | placeholder="è¯·æ«ææçç " |
| | | @keyup.enter="handlePalletScan" |
| | | @blur="loadPalletSummary" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-table> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | <el-form-item label="ç©ææ¡ç " required> |
| | | <el-input |
| | | ref="materialInput" |
| | | v-model="scanForm.materialBarcode" |
| | | placeholder="è¯·æ«æç©ææ¡ç " |
| | | :disabled="!scanForm.palletCode" |
| | | @keyup.enter="handleMaterialScan" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <!-- æå
å¼¹çª --> |
| | | <!-- æå
å¼¹çª --> |
| | | <div v-if="showCustomSplitDialog" class="custom-dialog-overlay"> |
| | | <div class="custom-dialog-wrapper"> |
| | | <div class="custom-dialog"> |
| | | <div class="custom-dialog-header"> |
| | | <h3>æå
æä½</h3> |
| | | <!-- <el-button |
| | | type="text" |
| | | icon="el-icon-close" |
| | | @click="closeCustomSplitDialog" |
| | | class="close-button"> |
| | | </el-button> --> |
| | | <el-button |
| | | type="text" |
| | | @click="closeCustomSplitDialog" |
| | | class="close-button"> |
| | | X |
| | | </el-button> |
| | | |
| | | <!-- æçæ£è´§ç»è®¡ --> |
| | | <div v-if="palletSummary" class="pallet-summary"> |
| | | <el-card header="æçæ£è´§ç»è®¡"> |
| | | <el-descriptions :column="3" border> |
| | | <el-descriptions-item label="æçå·"> |
| | | {{ scanForm.palletCode }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æªæ£è´§æ¡æ°"> |
| | | <el-text type="warning">{{ palletSummary.unpickedCount }}</el-text> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="æªæ£è´§æ»æ°"> |
| | | <el-text type="danger">{{ palletSummary.unpickedTotal }}</el-text> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> |
| | | </div> |
| | | |
| | | <div class="action-buttons"> |
| | | <el-button type="primary" @click="handleConfirm" :loading="confirmLoading"> |
| | | æå¨ç¡®è®¤ |
| | | </el-button> |
| | | <el-button @click="handleReset">éç½®</el-button> |
| | | <el-button @click="$emit('close')">åæ¶</el-button> |
| | | <div class="custom-dialog-body"> |
| | | <el-form :model="splitForm" :rules="splitFormRules" ref="splitFormRef" label-width="100px"> |
| | | <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.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> |
| | | </el-form-item> |
| | | <el-form-item label="ç©æç¼ç "> |
| | | <el-input v-model="splitForm.materielCode" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="å©ä½æ°é"> |
| | | <el-input v-model="splitForm.maxQuantity" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æå
æ°é" prop="splitQuantity"> |
| | | <el-input-number |
| | | v-model="splitForm.splitQuantity" |
| | | :min="1" |
| | | :max="splitForm.maxQuantity" |
| | | :precision="2" |
| | | :step="1" |
| | | style="width: 100%"> |
| | | </el-input-number> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeCustomSplitDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSplitPackage" :loading="splitLoading">确认æå
</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | |
| | | <!-- å³ä¾§ï¼åºåºè¯¦æ
å表 --> |
| | | <div class="right-section"> |
| | | <el-card class="outbound-details-card" header="åºåºè¯¦æ
"> |
| | | <vol-table |
| | | ref="outboundTable" |
| | | :table-config="outboundTableConfig" |
| | | :height="300" |
| | | /> |
| | | </el-card> |
| | | <!-- æ¤éæå
å¼¹çª --> |
| | | <div v-if="showRevertSplitDialog" 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="closeRevertSplitDialog" |
| | | class="close-button"> |
| | | Ã |
| | | </el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form |
| | | :model="revertSplitForm" |
| | | :rules="revertSplitFormRules" |
| | | ref="revertSplitFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="åæ¡ç " prop="originalBarcode"> |
| | | <el-input |
| | | v-model="revertSplitForm.originalBarcode" |
| | | placeholder="æ«æåæ¡ç " |
| | | @keyup.enter.native="onRevertSplitBarcodeScan" |
| | | @change="onRevertSplitBarcodeScan" |
| | | clearable> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeRevertSplitDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleRevertSplit" :loading="revertSplitLoading">确认æ¤é</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å·²åæ£è®°å½å表 --> |
| | | <div class="picked-records"> |
| | | <el-card header="å·²åæ£è®°å½"> |
| | | <vol-table |
| | | ref="pickedTable" |
| | | :table-config="pickedTableConfig" |
| | | :height="300" |
| | | /> |
| | | </el-card> |
| | | |
| | | <!-- æ¹éååºå¼¹çª --> |
| | | <div v-if="showBatchReturnDialog" 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="closeBatchReturnDialog" |
| | | class="close-button"> |
| | | Ã |
| | | </el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form |
| | | :model="batchReturnForm" |
| | | :rules="batchReturnFormRules" |
| | | ref="batchReturnFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="batchReturnForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æçç¼å·" prop="palletCode"> |
| | | <el-input |
| | | v-model="batchReturnForm.palletCode" |
| | | placeholder="æ«ææçç " |
| | | @keyup.enter.native="onBatchReturnPalletScan" |
| | | @change="onBatchReturnPalletScan" |
| | | clearable> |
| | | </el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æªæ£éæ°é"> |
| | | <el-input v-model="batchReturnForm.unpickedCount" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æªæ£éæ¡æ°"> |
| | | <el-input v-model="batchReturnForm.unpickedQuantity" disabled></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeBatchReturnDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleBatchReturnConfirm" :loading="batchReturnLoading">确认ååº</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- ç´æ¥åºåºå¼¹çª --> |
| | | <div v-if="showDirectOutDialog" 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="closeDirectOutDialog" |
| | | class="close-button"> |
| | | Ã |
| | | </el-button> |
| | | </div> |
| | | <div class="custom-dialog-body"> |
| | | <el-form |
| | | :model="directOutForm" |
| | | :rules="directOutFormRules" |
| | | ref="directOutFormRef" |
| | | label-width="100px"> |
| | | <el-form-item label="订åç¼å·"> |
| | | <el-input v-model="directOutForm.orderNo" disabled></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="æçç¼å·" prop="palletCode"> |
| | | <el-input |
| | | v-model="directOutForm.palletCode" |
| | | placeholder="æ«ææçç " |
| | | @keyup.enter.native="onDirectOutPalletScan" |
| | | @change="onDirectOutPalletScan" |
| | | clearable> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="custom-dialog-footer"> |
| | | <el-button @click="closeDirectOutDialog">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleDirectOutConfirm" :loading="directOutLoading">确认åºåº</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <print-view ref="childs" @parentcall="parentcall"></print-view> |
| | | </template> |
| | | |
| | | <script> |
| | | import http from '@/api/http.js' |
| | | import { ref, defineComponent } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { useRoute } from 'vue-router' |
| | | import { ElMessage } from 'element-plus' |
| | | import { useRoute } from 'vue-router' |
| | | import printView from "@/extension/outbound/extend/printView.vue" |
| | | |
| | | export default defineComponent({ |
| | | name: 'PickingConfirm', |
| | | components: { |
| | | |
| | | }, |
| | | components: {printView}, |
| | | props: { |
| | | orderNo: { |
| | | type: String, |
| | |
| | | }, |
| | | emits: ['confirm', 'close'], |
| | | data() { |
| | | // å®ä¹æå
表åéªè¯è§å |
| | | const validateOriginalBarcode = (rule, value, callback) => { |
| | | if (!value || value.trim() === '') { |
| | | callback(new Error('请è¾å
¥åæ¡ç ')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | |
| | | const validateSplitQuantity = (rule, value, callback) => { |
| | | if (value === null || value === undefined || value === '') { |
| | | callback(new Error('请è¾å
¥æå
æ°é')); |
| | | } else if (value <= 0) { |
| | | callback(new Error('æå
æ°éå¿
须大äº0')); |
| | | } else if (this.splitForm.maxQuantity && value > this.splitForm.maxQuantity) { |
| | | callback(new Error('æå
æ°éä¸è½å¤§äºå©ä½æ°é')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | |
| | | // å®ä¹æ¤éæå
表åéªè¯è§å |
| | | const validateRevertOriginalBarcode = (rule, value, callback) => { |
| | | if (!value || value.trim() === '') { |
| | | callback(new Error('请è¾å
¥åæ¡ç ')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | // å®ä¹æ¹éååºè¡¨åéªè¯è§å |
| | | const validateBatchReturnPalletCode = (rule, value, callback) => { |
| | | if (!value || value.trim() === '') { |
| | | callback(new Error('请è¾å
¥æçç ')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | // å®ä¹ç´æ¥åºåºè¡¨åéªè¯è§å |
| | | const validateDirectOutPalletCode = (rule, value, callback) => { |
| | | if (!value || value.trim() === '') { |
| | | callback(new Error('请è¾å
¥æçç ')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }; |
| | | return { |
| | | scanForm: { |
| | | scanData: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | | materialBarcode: '' |
| | | barcode: '' |
| | | }, |
| | | palletSummary: null, |
| | | confirmLoading: false, |
| | | pickedTableConfig: { |
| | | url: '/api/outbound/getPickingRecords', |
| | | query: { orderNo: this.orderNo }, |
| | | columns: [ |
| | | { prop: 'TaskNo', label: 'ä»»å¡å·', width: 150 }, |
| | | { prop: 'Barcode', label: 'ç©ææ¡ç ', width: 150 }, |
| | | { prop: 'MaterielName', label: 'ç©æåç§°', width: 150 }, |
| | | { prop: 'PickQuantity', label: 'æ£è´§æ°é', width: 100 }, |
| | | { prop: 'LocationCode', label: 'è´§ä½', width: 120 }, |
| | | { prop: 'CreateTime', label: 'æ£è´§æ¶é´', width: 180 } |
| | | unpickedList: [], |
| | | pickedList: [], |
| | | selectedUnpickedRows: [], // æªæ£éå表éä¸çè¡ |
| | | selectedPickedRows: [], // å·²æ£éå表éä¸çè¡ |
| | | summary: { |
| | | unpickedCount: 0, |
| | | unpickedQuantity: 0, |
| | | pickedCount: 0 |
| | | }, |
| | | palletStatus: 'æªç¥', |
| | | showSplitDialog: false, |
| | | showRevertSplitDialog: false, |
| | | showCustomSplitDialog: false, // èªå®ä¹æå
å¼¹çªæ¾ç¤ºç¶æ |
| | | showBatchReturnDialog: false, // æ¹éååºå¼¹çªæ¾ç¤ºç¶æ |
| | | showReturnDialog: false, |
| | | splitLoading: false, |
| | | revertSplitLoading: false, |
| | | batchReturnLoading: false, // æ¹éååºå è½½ç¶æ |
| | | splitForm: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | | originalBarcode: '', |
| | | materielCode: '', |
| | | splitQuantity: 0, |
| | | maxQuantity: 0 |
| | | }, |
| | | // æå
表åéªè¯è§å |
| | | splitFormRules: { |
| | | originalBarcode: [ |
| | | { required: true, validator: validateOriginalBarcode, trigger: 'blur' } |
| | | ], |
| | | splitQuantity: [ |
| | | { required: true, validator: validateSplitQuantity, trigger: 'blur' } |
| | | ] |
| | | }, |
| | | // åºåºè¯¦æ
è¡¨æ ¼é
ç½® |
| | | outboundTableConfig: { |
| | | url: '/api/outbound/getOutboundDetails', |
| | | query: { orderNo: this.orderNo }, |
| | | columns: [ |
| | | { prop: 'OrderNo', label: 'åºåºåå·', width: 150 }, |
| | | { prop: 'MaterialCode', label: 'ç©æç¼å·', width: 120 }, |
| | | { prop: 'MaterialBarcode', label: 'ç©ææ¡ç ', width: 150 }, |
| | | { prop: 'BatchNo', label: 'æ¹æ¬¡å·', width: 120 }, |
| | | { prop: 'AssignQuantity', label: 'åé
åºåºé', width: 100 }, |
| | | { prop: 'PalletCode', label: 'æçç¼å·', width: 120 }, |
| | | { prop: 'Unit', label: 'åä½', width: 80 } |
| | | revertSplitForm: { |
| | | originalBarcode: '' |
| | | }, |
| | | // æ¤éæå
表åéªè¯è§å |
| | | revertSplitFormRules: { |
| | | originalBarcode: [ |
| | | { required: true, validator: validateRevertOriginalBarcode, trigger: 'blur' } |
| | | ] |
| | | }, |
| | | orderInfo: {orderNo:''} |
| | | // æ¹éååºè¡¨å |
| | | batchReturnForm: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | | unpickedCount: 0, |
| | | unpickedQuantity: 0 |
| | | }, |
| | | // æ¹éååºè¡¨åéªè¯è§å |
| | | batchReturnFormRules: { |
| | | palletCode: [ |
| | | { required: true, validator: validateBatchReturnPalletCode, trigger: 'blur' } |
| | | ] |
| | | }, |
| | | showDirectOutDialog: false, // ç´æ¥åºåºå¼¹çªæ¾ç¤ºç¶æ |
| | | directOutLoading: false, // ç´æ¥åºåºå è½½ç¶æ |
| | | directOutForm: { |
| | | orderNo: '', |
| | | palletCode: '' |
| | | }, |
| | | directOutFormRules: { |
| | | palletCode: [ |
| | | { required: true, validator: validateDirectOutPalletCode, trigger: 'blur' } |
| | | ] |
| | | }, |
| | | returnForm: { |
| | | orderNo: '', |
| | | palletCode: '', |
| | | barcode: '', |
| | | materielCode: '', |
| | | returnQuantity: 0 |
| | | }, |
| | | isProcessing: false // 鲿¢éå¤æäº¤ |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.loadOrderInfo(); |
| | | // ä»è·¯ç±åæ°è·å订åç¼å· |
| | | if (this.$route.query.orderNo) { |
| | | this.scanData.orderNo = this.$route.query.orderNo; |
| | | this.splitForm.orderNo = this.$route.query.orderNo; |
| | | this.returnForm.orderNo = this.$route.query.orderNo; |
| | | } |
| | | // 页é¢å è½½åèªå¨èç¦å°æçç è¾å
¥æ¡ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.palletInput) { |
| | | this.$refs.palletInput.focus() |
| | | } |
| | | }) |
| | | this.$refs.palletInput.focus(); |
| | | }); |
| | | |
| | | }, |
| | | methods: { |
| | | loadOrderInfo() { |
| | | const orderId = this.$route.query.orderId |
| | | if (!orderId) return |
| | | goBack(){ |
| | | this.$router.back() |
| | | }, |
| | | |
| | | openSplitDialog() { |
| | | console.log('æå¼èªå®ä¹æå
å¼¹çª'); |
| | | if (!this.scanData.palletCode) { |
| | | this.$message.warning('请å
æ«ææçç '); |
| | | return; |
| | | } |
| | | this.showCustomSplitDialog = true; |
| | | |
| | | // é置表å |
| | | this.resetSplitForm(); |
| | | |
| | | // 设置订ååæçä¿¡æ¯ |
| | | this.splitForm.orderNo = this.scanData.orderNo; |
| | | this.splitForm.palletCode = this.scanData.palletCode; |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.splitFormRef) { |
| | | this.$refs.splitFormRef.clearValidate(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å
³éèªå®ä¹æå
å¼¹çª |
| | | closeCustomSplitDialog() { |
| | | this.showCustomSplitDialog = false; |
| | | this.resetSplitForm(); |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | if (this.$refs.splitFormRef) { |
| | | this.$refs.splitFormRef.clearValidate(); |
| | | } |
| | | }, |
| | | |
| | | // æå¼æ¤éæå
å¼¹çª |
| | | openRevertSplitDialog() { |
| | | console.log('æå¼æ¤éæå
å¼¹çª'); |
| | | this.showRevertSplitDialog = true; |
| | | |
| | | // é置表å |
| | | this.resetRevertSplitForm(); |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.revertSplitFormRef) { |
| | | this.$refs.revertSplitFormRef.clearValidate(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å
³éæ¤éæå
å¼¹çª |
| | | closeRevertSplitDialog() { |
| | | this.showRevertSplitDialog = false; |
| | | this.resetRevertSplitForm(); |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | if (this.$refs.revertSplitFormRef) { |
| | | this.$refs.revertSplitFormRef.clearValidate(); |
| | | } |
| | | }, |
| | | // æå¼æ¹éååºå¼¹çª |
| | | openBatchReturnDialog() { |
| | | console.log('æå¼æ¹éååºå¼¹çª'); |
| | | this.showBatchReturnDialog = true; |
| | | |
| | | // é置表å |
| | | this.resetBatchReturnForm(); |
| | | |
| | | // 设置订åä¿¡æ¯ |
| | | this.batchReturnForm.orderNo = this.scanData.orderNo; |
| | | |
| | | // æ´æ°æªæ£éä¿¡æ¯ |
| | | this.batchReturnForm.unpickedCount = this.summary.unpickedCount || 0; |
| | | this.batchReturnForm.unpickedQuantity = this.summary.unpickedQuantity || 0; |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.batchReturnFormRef) { |
| | | this.$refs.batchReturnFormRef.clearValidate(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å
³éæ¹éååºå¼¹çª |
| | | closeBatchReturnDialog() { |
| | | this.showBatchReturnDialog = false; |
| | | this.resetBatchReturnForm(); |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | if (this.$refs.batchReturnFormRef) { |
| | | this.$refs.batchReturnFormRef.clearValidate(); |
| | | } |
| | | }, |
| | | |
| | | // ååºæçç æ«ç |
| | | onBatchReturnPalletScan() { |
| | | if (!this.batchReturnForm.palletCode) return; |
| | | |
| | | this.batchReturnForm.palletCode = this.batchReturnForm.palletCode.replace(/\n/g, '').trim(); |
| | | |
| | | // æ¸
é¤éªè¯ç¶æ |
| | | if (this.$refs.batchReturnFormRef) { |
| | | this.$refs.batchReturnFormRef.clearValidate(['palletCode']); |
| | | } |
| | | }, |
| | | |
| | | // ååºç¡®è®¤ |
| | | async handleBatchReturnConfirm() { |
| | | // 表åéªè¯ |
| | | if (this.$refs.batchReturnFormRef) { |
| | | this.$refs.batchReturnFormRef.validate((valid) => { |
| | | if (valid) { |
| | | this.submitBatchReturn(); |
| | | } else { |
| | | this.$message.warning('è¯·æ«ææçç '); |
| | | return false; |
| | | } |
| | | }); |
| | | } else { |
| | | // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ |
| | | if (!this.batchReturnForm.palletCode) { |
| | | this.$message.warning('è¯·æ«ææçç '); |
| | | return; |
| | | } |
| | | |
| | | this.submitBatchReturn(); |
| | | } |
| | | }, |
| | | |
| | | // æäº¤ååºè¯·æ± |
| | | async submitBatchReturn() { |
| | | this.batchReturnLoading = true; |
| | | |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/return-to-stock', { |
| | | orderNo: this.batchReturnForm.orderNo, |
| | | palletCode: this.batchReturnForm.palletCode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success(res.message); |
| | | this.showBatchReturnDialog = false; |
| | | this.loadData(); |
| | | } else { |
| | | this.$message.error(res.message || 'ååºå¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('ååºå¤±è´¥'); |
| | | } finally { |
| | | this.batchReturnLoading = false; |
| | | } |
| | | }, |
| | | // æå¼ç´æ¥åºåºå¼¹çª |
| | | openDirectOutDialog() { |
| | | console.log('æå¼ç´æ¥åºåºå¼¹çª'); |
| | | this.showDirectOutDialog = true; |
| | | |
| | | // é置表å |
| | | this.resetDirectOutForm(); |
| | | |
| | | // 设置订åä¿¡æ¯ |
| | | this.directOutForm.orderNo = this.scanData.orderNo; |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | this.$nextTick(() => { |
| | | if (this.$refs.directOutFormRef) { |
| | | this.$refs.directOutFormRef.clearValidate(); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å
³éç´æ¥åºåºå¼¹çª |
| | | closeDirectOutDialog() { |
| | | this.showDirectOutDialog = false; |
| | | this.resetDirectOutForm(); |
| | | |
| | | // æ¸
é¤è¡¨åéªè¯ |
| | | if (this.$refs.directOutFormRef) { |
| | | this.$refs.directOutFormRef.clearValidate(); |
| | | } |
| | | }, |
| | | |
| | | // ç´æ¥åºåºæçç æ«ç |
| | | onDirectOutPalletScan() { |
| | | if (!this.directOutForm.palletCode) return; |
| | | |
| | | this.directOutForm.palletCode = this.directOutForm.palletCode.replace(/\n/g, '').trim(); |
| | | |
| | | // æ¸
é¤éªè¯ç¶æ |
| | | if (this.$refs.directOutFormRef) { |
| | | this.$refs.directOutFormRef.clearValidate(['palletCode']); |
| | | } |
| | | }, |
| | | |
| | | // ç´æ¥åºåºç¡®è®¤ |
| | | async handleDirectOutConfirm() { |
| | | // 表åéªè¯ |
| | | if (this.$refs.directOutFormRef) { |
| | | this.$refs.directOutFormRef.validate((valid) => { |
| | | if (valid) { |
| | | this.submitDirectOut(); |
| | | } else { |
| | | this.$message.warning('è¯·æ«ææçç '); |
| | | return false; |
| | | } |
| | | }); |
| | | } else { |
| | | // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ |
| | | if (!this.directOutForm.palletCode) { |
| | | this.$message.warning('è¯·æ«ææçç '); |
| | | return; |
| | | } |
| | | |
| | | this.submitDirectOut(); |
| | | } |
| | | }, |
| | | |
| | | // æäº¤ç´æ¥åºåºè¯·æ± |
| | | async submitDirectOut() { |
| | | this.directOutLoading = true; |
| | | |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/direct-outbound', { |
| | | orderNo: this.directOutForm.orderNo, |
| | | palletCode: this.directOutForm.palletCode |
| | | }); |
| | | debugger; |
| | | if (res.status) { |
| | | this.$message.success('ç´æ¥åºåºæå'); |
| | | this.showDirectOutDialog = false; |
| | | this.loadData(); |
| | | } else { |
| | | this.$message.error(res.message || 'ç´æ¥åºåºå¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('ç´æ¥åºåºå¤±è´¥'); |
| | | } finally { |
| | | this.directOutLoading = false; |
| | | } |
| | | }, |
| | | |
| | | // éç½®ç´æ¥åºåºè¡¨å |
| | | resetDirectOutForm() { |
| | | this.directOutForm.palletCode = ''; |
| | | }, |
| | | |
| | | // ä¿®æ¹åæçç´æ¥åºåºæé®ç¹å»äºä»¶ |
| | | handleDirectOutbound() { |
| | | this.openDirectOutDialog(); |
| | | }, |
| | | async loadData() { |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode) { |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | this.http.get(`/api/OutboundOrder/GetById?id=${orderId}`).then(response => {debugger; |
| | | if (response.status) { |
| | | this.orderInfo = response.data |
| | | // å è½½æªæ£éå表 |
| | | const unpickedRes = await this.http.post('/api/OutboundPicking/unpicked-list', this.scanData); |
| | | this.unpickedList = unpickedRes.data || []; |
| | | |
| | | // å 载已æ£éå表 |
| | | const pickedRes = await this.http.post('/api/OutboundPicking/picked-list', this.scanData); |
| | | this.pickedList = pickedRes.data || []; |
| | | |
| | | // å è½½æ±æ»ä¿¡æ¯ |
| | | const summaryRes = await this.http.post('/api/OutboundPicking/picking-summary',this.scanData); |
| | | this.summary = summaryRes.data || {}; |
| | | |
| | | // æ´æ°æçç¶æ |
| | | this.updatePalletStatus(); |
| | | |
| | | } catch (error) { |
| | | this.$message.error('å è½½æ°æ®å¤±è´¥'); |
| | | } |
| | | }, |
| | | |
| | | updatePalletStatus() { |
| | | if (this.unpickedList.length === 0 && this.pickedList.length > 0) { |
| | | this.palletStatus = 'å·²å
¨é¨æ£é'; |
| | | } else if (this.unpickedList.length > 0 && this.pickedList.length === 0) { |
| | | this.palletStatus = 'å¾
æ£é'; |
| | | } else if (this.unpickedList.length > 0 && this.pickedList.length > 0) { |
| | | this.palletStatus = 'é¨åæ£é'; |
| | | } else { |
| | | this.palletStatus = 'æ æ°æ®'; |
| | | } |
| | | }, |
| | | // å·²æ£éåè¡¨éæ©åå |
| | | handlePickedSelectionChange(selection) { |
| | | this.selectedPickedRows = selection; |
| | | }, |
| | | // æ¹éåæ¶éä¸çå·²æ£é项 |
| | | async batchCancelSelected() { |
| | | if (this.selectedPickedRows.length === 0) { |
| | | this.$message.warning('请å
éæ©è¦åæ¶ç项'); |
| | | return; |
| | | } |
| | | |
| | | this.$confirm(`ç¡®å®è¦åæ¶éä¸ç ${this.selectedPickedRows.length} 项åï¼`, 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(async () => { |
| | | try { |
| | | let successCount = 0; |
| | | let errorCount = 0; |
| | | |
| | | for (const row of this.selectedPickedRows) { |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/CancelPicking', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | barcode: row.currentBarcode |
| | | }); |
| | | |
| | | } |
| | | }) |
| | | } catch (error) { |
| | | ElMessage.error('å è½½åºåºåä¿¡æ¯å¤±è´¥') |
| | | } |
| | | }, |
| | | goBack() { |
| | | this.$router.back() |
| | | }, |
| | | async handlePalletScan() { |
| | | if (this.scanForm.palletCode) { |
| | | ElMessage.success(`å·²æ«ææç: ${this.scanForm.palletCode}`) |
| | | await this.loadPalletSummary() |
| | | |
| | | this.$nextTick(() => { |
| | | if (this.$refs.materialInput) { |
| | | this.$refs.materialInput.focus() |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | async handleMaterialScan() { |
| | | if (!this.scanForm.palletCode) { |
| | | ElMessage.warning('请å
æ«ææçç ') |
| | | this.$refs.palletInput.focus() |
| | | return |
| | | } |
| | | |
| | | if (!this.scanForm.materialBarcode) { |
| | | ElMessage.warning('è¯·æ«æç©ææ¡ç ') |
| | | return |
| | | } |
| | | |
| | | await this.executePickingConfirm() |
| | | }, |
| | | async loadPalletSummary() { |
| | | if (!this.scanForm.palletCode) { |
| | | this.palletSummary = null |
| | | return |
| | | } |
| | | |
| | | try { |
| | | const result = await http.get('/api/outbound/getPalletPickingSummary', { |
| | | params: { |
| | | orderNo: this.orderNo, |
| | | palletCode: this.scanForm.palletCode |
| | | } |
| | | }) |
| | | |
| | | if (result.success) { |
| | | // å¤çç»è®¡ä¿¡æ¯ |
| | | const summary = result.data |
| | | const assigned = summary.find(x => x.Status === 'å·²åé
') || { TotalAssignQty: 0, TotalPickedQty: 0 } |
| | | const picked = summary.find(x => x.Status === 'å·²æ£é') || { TotalPickedQty: 0 } |
| | | |
| | | this.palletSummary = { |
| | | unpickedCount: assigned.TotalAssignQty > 0 ? 1 : 0, // ç®åè®¡ç® |
| | | unpickedTotal: assigned.TotalAssignQty - assigned.TotalPickedQty |
| | | } |
| | | } |
| | | } catch (error) { |
| | | console.error('å è½½æçç»è®¡å¤±è´¥:', error) |
| | | } |
| | | }, |
| | | async handleConfirm() { |
| | | if (!this.scanForm.palletCode || !this.scanForm.materialBarcode) { |
| | | ElMessage.warning('请填å宿´çæ«ç ä¿¡æ¯') |
| | | return |
| | | } |
| | | |
| | | await this.executePickingConfirm() |
| | | }, |
| | | async executePickingConfirm() { |
| | | this.confirmLoading = true |
| | | |
| | | try { |
| | | // å
æ¾å°å¯¹åºçåºåºéå®ä¿¡æ¯ |
| | | const lockInfoResult = await this.http.get('/api/outbound/getOutStockLockInfo', { |
| | | params: { |
| | | orderNo: this.orderNo, |
| | | palletCode: this.scanForm.palletCode, |
| | | materialBarcode: this.scanForm.materialBarcode |
| | | } |
| | | }) |
| | | |
| | | if (!lockInfoResult.success || !lockInfoResult.data || lockInfoResult.data.length === 0) { |
| | | ElMessage.error('æªæ¾å°å¯¹åºçåºåºéå®ä¿¡æ¯') |
| | | return |
| | | } |
| | | |
| | | const lockInfo = lockInfoResult.data[0] |
| | | |
| | | const request = { |
| | | outStockLockId: lockInfo.Id, |
| | | taskNo: `TASK_${Date.now()}`, |
| | | palletCode: this.scanForm.palletCode, |
| | | materialBarcode: this.scanForm.materialBarcode, |
| | | locationCode: lockInfo.LocationCode |
| | | } |
| | | |
| | | const result = await this.http.post('/api/outbound/pickingConfirm', request) |
| | | |
| | | if (result.success) { |
| | | ElMessage.success('åæ£ç¡®è®¤æå') |
| | | this.handleReset() |
| | | this.$emit('confirm') |
| | | |
| | | // å·æ°è¡¨æ ¼ |
| | | if (this.$refs.pickedTable) { |
| | | this.$refs.pickedTable.refresh() |
| | | if (res.status) { |
| | | successCount++; |
| | | } else { |
| | | errorCount++; |
| | | console.error(`åæ¶æ£é失败: ${row.Barcode}`, res.message); |
| | | } |
| | | } catch (error) { |
| | | errorCount++; |
| | | console.error(`åæ¶æ£é失败: ${row.Barcode}`, error); |
| | | } |
| | | } |
| | | |
| | | // å·æ°åºåºè¯¦æ
è¡¨æ ¼ |
| | | if (this.$refs.outboundTable) { |
| | | this.$refs.outboundTable.refresh() |
| | | if (errorCount === 0) { |
| | | this.$message.success(`æååæ¶ ${successCount} 项`); |
| | | } else { |
| | | this.$message.warning(`æååæ¶ ${successCount} 项ï¼å¤±è´¥ ${errorCount} 项`); |
| | | } |
| | | |
| | | this.loadData(); |
| | | this.selectedPickedRows = []; |
| | | } catch (error) { |
| | | this.$message.error('æ¹éåæ¶æä½å¤±è´¥'); |
| | | } |
| | | }).catch(() => { |
| | | this.$message.info('已忶æ¹éæä½'); |
| | | }); |
| | | }, |
| | | // æçç æ«ç |
| | | onPalletScan() { |
| | | // å»é¤å车符åååç©ºæ ¼ |
| | | this.scanData.palletCode = this.scanData.palletCode.replace(/\n/g, '').trim(); |
| | | if (!this.scanData.palletCode) return; |
| | | |
| | | this.splitForm.palletCode = this.scanData.palletCode; |
| | | this.returnForm.palletCode = this.scanData.palletCode; |
| | | |
| | | // å è½½æ°æ® |
| | | this.loadData(); |
| | | |
| | | // èªå¨è·³è½¬å°ç©ææ¡ç è¾å
¥æ¡ |
| | | this.$nextTick(() => { |
| | | this.$refs.barcodeInput.focus(); |
| | | }); |
| | | }, |
| | | |
| | | // éæ°å è½½æçç»è®¡ |
| | | await this.loadPalletSummary() |
| | | onBarcodeScan() { |
| | | // å»é¤å车符åååç©ºæ ¼ |
| | | this.scanData.barcode = this.scanData.barcode.replace(/\n/g, '').trim(); |
| | | if (!this.scanData.barcode) return; |
| | | |
| | | // èªå¨ç¡®è®¤æ£é |
| | | this.confirmPicking(); |
| | | }, |
| | | |
| | | async confirmPicking() { |
| | | if (this.isProcessing) return; |
| | | |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode || !this.scanData.barcode) { |
| | | this.$message.warning('请å
æ«ææçç åç©ææ¡ç '); |
| | | this.focusBarcodeInput(); |
| | | return; |
| | | } |
| | | |
| | | this.isProcessing = true; |
| | | |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/confirm-picking', this.scanData); |
| | | if (res.status) { |
| | | this.$message.success('æ£é确认æå'); |
| | | this.scanData.barcode = ''; // æ¸
ç©ºç©ææ¡ç |
| | | this.loadData(); |
| | | console.log(res.data.splitResults) |
| | | if(res.data && res.data.splitResults.length>0){ |
| | | // è°ç¨åç»ä»¶æå°æ¹æ³ |
| | | this.$refs.childs.open(res.data.splitResults); |
| | | //this.$refs.childs.printSplitLabel(res.data.splitResults); |
| | | } |
| | | // æååç»§ç»èç¦å°ç©ææ¡ç è¾å
¥æ¡ï¼åå¤ä¸ä¸ä¸ªæ«ç |
| | | this.$nextTick(() => { |
| | | this.$refs.barcodeInput.focus(); |
| | | }); |
| | | } else { |
| | | ElMessage.error(result.ElMessage) |
| | | // æ¾ç¤ºå端è¿åçéè¯¯ä¿¡æ¯ |
| | | this.$message.error(res.message || 'æ£é确认失败'); |
| | | // 失败æ¶èç¦å¹¶éä¸ç©ææ¡ç è¾å
¥æ¡å
容 |
| | | this.focusBarcodeInput(true); |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('åæ£ç¡®è®¤å¤±è´¥') |
| | | this.$message.error('æ£é确认失败: ' + (error.message || 'ç½ç»é误')); |
| | | // 失败æ¶èç¦å¹¶éä¸ç©ææ¡ç è¾å
¥æ¡å
容 |
| | | this.focusBarcodeInput(true); |
| | | } finally { |
| | | this.confirmLoading = false |
| | | this.isProcessing = false; |
| | | } |
| | | }, |
| | | handleReset() { |
| | | this.scanForm.materialBarcode = '' |
| | | |
| | | // èç¦å°ç©ææ¡ç è¾å
¥æ¡ |
| | | focusBarcodeInput(selectText = false) { |
| | | this.$nextTick(() => { |
| | | if (this.$refs.materialInput) { |
| | | this.$refs.materialInput.focus() |
| | | const input = this.$refs.barcodeInput; |
| | | if (input && input.$el && input.$el.querySelector('input')) { |
| | | const inputEl = input.$el.querySelector('input'); |
| | | inputEl.focus(); |
| | | if (selectText) { |
| | | inputEl.select(); |
| | | } |
| | | } |
| | | }) |
| | | }); |
| | | }, |
| | | |
| | | async cancelPicking(row) { |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/CancelPicking', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode, |
| | | barcode: row.Barcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('åæ¶æ£éæå'); |
| | | this.loadData(); |
| | | } else { |
| | | this.$message.error(res.message || 'åæ¶æ£é失败'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('åæ¶æ£é失败'); |
| | | } |
| | | }, |
| | | |
| | | /* // ååºæä½ - ååºæ´ä¸ªæçæªæ£éçè´§ç© |
| | | async handleBatchReturn() { |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode) { |
| | | this.$message.warning('请å
æ«ææçç '); |
| | | return; |
| | | } |
| | | |
| | | if (this.unpickedList.length === 0) { |
| | | this.$message.warning('该æç没æå¯ååºçè´§ç©'); |
| | | return; |
| | | } |
| | | |
| | | this.$confirm(`ç¡®å®è¦ååºæ´ä¸ªæççæªæ£éè´§ç©åï¼å
± ${this.unpickedList.length} æ¡è®°å½`, 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(async () => { |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/batch-return-to-stock', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | |
| | | if (res.success) { |
| | | this.$message.success('æ¹éååºæå'); |
| | | this.loadData(); |
| | | } else { |
| | | this.$message.error(res.message || 'æ¹éååºå¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ¹éååºå¤±è´¥'); |
| | | } |
| | | }).catch(() => { |
| | | this.$message.info('已忶æ¹éååº'); |
| | | }); |
| | | }, */ |
| | | |
| | | /* // ç´æ¥åºåºæä½ |
| | | async handleDirectOutbound() { |
| | | if (!this.scanData.orderNo || !this.scanData.palletCode) { |
| | | this.$message.warning('请å
æ«ææçç '); |
| | | return; |
| | | } |
| | | |
| | | this.$confirm('ç¡®å®è¦ç´æ¥åºåºæ´ä¸ªæçåï¼', 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(async () => { |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/direct-outbound', { |
| | | orderNo: this.scanData.orderNo, |
| | | palletCode: this.scanData.palletCode |
| | | }); |
| | | |
| | | if (res.success) { |
| | | this.$message.success('ç´æ¥åºåºæå'); |
| | | this.loadData(); |
| | | } else { |
| | | this.$message.error(res.message || 'ç´æ¥åºåºå¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('ç´æ¥åºåºå¤±è´¥'); |
| | | } |
| | | }).catch(() => { |
| | | this.$message.info('å·²åæ¶ç´æ¥åºåº'); |
| | | }); |
| | | }, */ |
| | | // 确认ååºï¼éè¿å¼¹çªï¼ |
| | | async handleReturnConfirm() { |
| | | if (!this.returnForm.barcode) { |
| | | this.$message.warning('è¯·æ«æååºæ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/return-to-stock', { |
| | | orderNo: this.returnForm.orderNo, |
| | | palletCode: this.returnForm.palletCode, |
| | | barcode: this.returnForm.barcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('ååºæå'); |
| | | this.showReturnDialog = false; |
| | | this.resetReturnForm(); |
| | | this.loadData(); |
| | | } else { |
| | | this.$message.error(res.message || 'ååºå¤±è´¥'); |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('ååºå¤±è´¥'); |
| | | } |
| | | }, |
| | | |
| | | // æå
æ«ç |
| | | async onSplitBarcodeScan() { |
| | | if (!this.splitForm.originalBarcode) return; |
| | | |
| | | // å»é¤å车符åååç©ºæ ¼ |
| | | this.splitForm.originalBarcode = this.splitForm.originalBarcode.replace(/\n/g, '').trim(); |
| | | |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/split-package-info', { |
| | | |
| | | orderNo: this.splitForm.orderNo, |
| | | palletCode: this.splitForm.palletCode, |
| | | barcode: this.splitForm.originalBarcode |
| | | |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.splitForm.materielCode = res.data.materielCode; |
| | | this.splitForm.maxQuantity = res.data.remainQuantity; |
| | | this.splitForm.splitQuantity = Math.min(1, this.splitForm.maxQuantity); |
| | | // æ¸
é¤éªè¯ç¶æ |
| | | if (this.$refs.splitFormRef) { |
| | | this.$refs.splitFormRef.clearValidate(['originalBarcode']); |
| | | } |
| | | } else { |
| | | this.$message.error(res.message || 'è·åæå
ä¿¡æ¯å¤±è´¥'); |
| | | // éªè¯å¤±è´¥ï¼è®¾ç½®éè¯¯ç¶æ |
| | | if (this.$refs.splitFormRef) { |
| | | this.$refs.splitFormRef.validateField('originalBarcode'); |
| | | } |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('è·åæå
ä¿¡æ¯å¤±è´¥'); |
| | | // éªè¯å¤±è´¥ï¼è®¾ç½®éè¯¯ç¶æ |
| | | if (this.$refs.splitFormRef) { |
| | | this.$refs.splitFormRef.validateField('originalBarcode'); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | async handleSplitPackage() { |
| | | // 表åéªè¯ |
| | | if (this.$refs.splitFormRef) { |
| | | this.$refs.splitFormRef.validate((valid) => { |
| | | if (valid) { |
| | | this.submitSplitPackage(); |
| | | } else { |
| | | this.$message.warning('请填å宿´çæå
ä¿¡æ¯'); |
| | | return false; |
| | | } |
| | | }); |
| | | } else { |
| | | // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ |
| | | if (!this.splitForm.originalBarcode || this.splitForm.splitQuantity <= 0) { |
| | | this.$message.warning('请填å宿´çæå
ä¿¡æ¯'); |
| | | return; |
| | | } |
| | | |
| | | if (this.splitForm.splitQuantity > this.splitForm.maxQuantity) { |
| | | this.$message.warning('æå
æ°éä¸è½å¤§äºå©ä½æ°é'); |
| | | return; |
| | | } |
| | | |
| | | this.submitSplitPackage(); |
| | | } |
| | | |
| | | |
| | | }, |
| | | // æäº¤æå
è¯·æ± |
| | | async submitSplitPackage() { |
| | | this.splitLoading = true; |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/split-package', this.splitForm); |
| | | if (res.status) { |
| | | this.$message.success('æå
æå'); |
| | | this.showSplitDialog = false; |
| | | this.splitLoading = false; |
| | | this.resetSplitForm(); |
| | | this.loadData(); |
| | | } else { |
| | | this.splitLoading = false; |
| | | this.$message.error(res.message || 'æå
失败'); |
| | | } |
| | | } catch (error) { |
| | | this.splitLoading = false; |
| | | this.$message.error('æå
失败'); |
| | | } |
| | | }, |
| | | // æ¤éæå
æ«ç |
| | | onRevertSplitBarcodeScan() { |
| | | if (!this.revertSplitForm.originalBarcode) return; |
| | | |
| | | this.revertSplitForm.originalBarcode = this.revertSplitForm.originalBarcode.replace(/\n/g, '').trim(); |
| | | |
| | | // æ¸
é¤éªè¯ç¶æ |
| | | if (this.$refs.revertSplitFormRef) { |
| | | this.$refs.revertSplitFormRef.clearValidate(['originalBarcode']); |
| | | } |
| | | }, |
| | | async handleRevertSplit() { |
| | | // 表åéªè¯ |
| | | if (this.$refs.revertSplitFormRef) { |
| | | this.$refs.revertSplitFormRef.validate((valid) => { |
| | | if (valid) { |
| | | this.submitRevertSplit(); |
| | | } else { |
| | | this.$message.warning('请è¾å
¥åæ¡ç '); |
| | | return false; |
| | | } |
| | | }); |
| | | } else { |
| | | // å¦ææ²¡æè¡¨åå¼ç¨ï¼ä½¿ç¨åæçéªè¯ |
| | | if (!this.revertSplitForm.originalBarcode) { |
| | | this.$message.warning('请è¾å
¥åæ¡ç '); |
| | | return; |
| | | } |
| | | |
| | | this.submitRevertSplit(); |
| | | } |
| | | }, |
| | | // æäº¤æ¤éæå
è¯·æ± |
| | | async submitRevertSplit() { |
| | | this.revertSplitLoading = true; |
| | | |
| | | try { |
| | | const res = await this.http.post('/api/OutboundPicking/revert-split-package', { |
| | | originalBarcode: this.revertSplitForm.originalBarcode |
| | | }); |
| | | |
| | | if (res.status) { |
| | | this.$message.success('æ¤éæå
æå'); |
| | | this.showRevertSplitDialog = false; |
| | | this.revertSplitLoading = false; |
| | | this.revertSplitForm.originalBarcode = ''; |
| | | this.loadData(); |
| | | } else { |
| | | this.revertSplitLoading = false; |
| | | this.$message.error(res.message || 'æ¤éæå
失败'); |
| | | } |
| | | } catch (error) { |
| | | this.revertSplitLoading = false; |
| | | this.$message.error('æ¤éæå
失败'); |
| | | } |
| | | }, |
| | | resetSplitForm() { |
| | | this.splitForm.originalBarcode = ''; |
| | | this.splitForm.materielCode = ''; |
| | | this.splitForm.splitQuantity = 0; |
| | | this.splitForm.maxQuantity = 0; |
| | | }, |
| | | // éç½®æ¹éååºè¡¨å |
| | | resetBatchReturnForm() { |
| | | this.batchReturnForm.palletCode = ''; |
| | | this.batchReturnForm.unpickedCount = 0; |
| | | this.batchReturnForm.unpickedQuantity = 0; |
| | | }, |
| | | resetReturnForm() { |
| | | this.returnForm.barcode = ''; |
| | | this.returnForm.materielCode = ''; |
| | | this.returnForm.returnQuantity = 0; |
| | | } |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .picking-confirm { |
| | | .picking-container { |
| | | padding: 20px; |
| | | position: relative; /* 为弹çªå®ä½æä¾ä¸ä¸æ */ |
| | | } |
| | | .scanner-form { |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 70vh; |
| | | gap: 10px; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .content-layout { |
| | | .scanner-form .el-input { |
| | | width: 200px; |
| | | } |
| | | .summary-info { |
| | | display: flex; |
| | | gap: 16px; |
| | | margin-bottom: 16px; |
| | | flex: 1; |
| | | min-height: 0; /* éè¦ï¼é²æ¢flexåå
ç´ æº¢åº */ |
| | | gap: 20px; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .left-section { |
| | | flex: 1; |
| | | /* è¡¨æ ¼æä½åºåæ ·å¼ */ |
| | | .table-actions { |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | padding: 0 10px; |
| | | } |
| | | |
| | | .right-section { |
| | | flex: 1; |
| | | .selection-count { |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | /* è¡¨æ ¼æ ·å¼è°æ´ */ |
| | | .content-area .el-table { |
| | | margin-top: 0; |
| | | } |
| | | |
| | | /* ç¡®ä¿è¡¨æ ¼é«åº¦éåº */ |
| | | .content-area .el-card__body { |
| | | padding: 15px; |
| | | } |
| | | |
| | | |
| | | /* èªå®ä¹å¼¹çªæ ·å¼ */ |
| | | .custom-dialog-overlay { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: rgba(0, 0, 0, 0.5); |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 9999; |
| | | } |
| | | |
| | | .scan-section { |
| | | flex-shrink: 0; |
| | | .custom-dialog-wrapper { |
| | | position: relative; |
| | | z-index: 10000; |
| | | } |
| | | |
| | | .scan-alert { |
| | | margin-bottom: 16px; |
| | | .custom-dialog { |
| | | background: white; |
| | | border-radius: 4px; |
| | | width: 500px; |
| | | max-width: 90vw; |
| | | max-height: 90vh; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | overflow: auto; |
| | | } |
| | | |
| | | .scan-form { |
| | | max-width: 500px; |
| | | } |
| | | |
| | | .pallet-summary { |
| | | margin: 16px 0; |
| | | } |
| | | |
| | | .action-buttons { |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .outbound-details-card { |
| | | height: 100%; |
| | | .custom-dialog-header { |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 20px 20px 10px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .outbound-details-card :deep(.el-card__body) { |
| | | flex: 1; |
| | | .custom-dialog-header h3 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | /* å
³éæé®æ ·å¼ */ |
| | | .close-button { |
| | | font-size: 18px; |
| | | color: #909399; |
| | | padding: 0; |
| | | width: 24px; |
| | | height: 24px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .picked-records { |
| | | flex-shrink: 0; |
| | | height: 300px; |
| | | .close-button:hover { |
| | | color: #409EFF; |
| | | background-color: transparent; |
| | | } |
| | | |
| | | .picked-records :deep(.el-card__body) { |
| | | padding: 0; |
| | | .custom-dialog-body { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .custom-dialog-footer { |
| | | padding: 10px 20px 20px; |
| | | text-align: right; |
| | | border-top: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .custom-dialog-footer .el-button { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | /* ç¡®ä¿å¼¹çªå¨ç§»å¨è®¾å¤ä¸ä¹è½æ£å¸¸æ¾ç¤º */ |
| | | @media (max-width: 768px) { |
| | | .custom-dialog { |
| | | width: 95vw; |
| | | margin: 10px; |
| | | } |
| | | } |
| | | </style> |