|
|
<template> <div> <div class="pda-container" v-loading.fullscreen.lock="fullscreenLoading" element-loading-background="rgba(255, 255, 255, 0.3)" element-loading-spinner="el-icon-loading" :element-loading-text="loadingText"> <div class="status-bar"> <div class="goBack" @click="handleBack"><i class="el-icon-arrow-left"></i>上一页</div> <div class="goBack">登记到达</div> <div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div> </div> <div style="overflow-y: auto"> <!-- Step 1: 扫描 --> <div v-if="processFlag === 1"> <div class="scan-box" style="margin: 2px;"> <el-input clearable v-model="scanCode" placeholder="扫描PO条码或输入PO号" inputmode="none" autocomplete="off" autocorrect="off" spellcheck="false" @keyup.enter.native="searchPoList" ref="scanCodeRef" /> </div> <div class="item-list" v-if="poList.length > 0" style="margin: 2px;"> <el-form label-position="top" style="margin: 3px;"> <el-row :gutter="5" @click.native="recvLine(poDetail)" v-for="(poDetail, index) in poList" :key="index" :class="index < poList.length - 1 ? 'bottom-line-row' : ''"> <el-col :span="8"> <el-form-item label="商品编码"><span>{{ poDetail.partNo }}</span></el-form-item> </el-col> <el-col :span="8"> <el-form-item label="行号/下达号"><span>{{ poDetail.lineNo }}/{{ poDetail.wdr || '*' }}</span></el-form-item> </el-col> <el-col :span="8"> <el-form-item label=""> <el-button type="text" class="recvButton" @click="recvLine(poDetail)" style="margin-top: 10px;margin-left: 20px" size="small">接收</el-button> </el-form-item> </el-col> <el-col :span="24"> <el-form-item label="商品描述"><span>{{ poDetail.description }}</span></el-form-item> </el-col> <el-col :span="6" :class="{ mt10: getTextWidth(poDetail.description) > 34 }"> <el-form-item label="订单数量"><span>{{ poDetail.purchaseQty }}</span></el-form-item> </el-col> <el-col :span="6" :class="{ mt10: getTextWidth(poDetail.description) > 34 }"> <el-form-item label="待收数量"><span>{{ poDetail.qtyToReceive }}</span></el-form-item> </el-col> <el-col :span="6" :class="{ mt10: getTextWidth(poDetail.description) > 34 }"> <el-form-item label="计划数量"><span>{{ poDetail.invQtyToReceive }}</span></el-form-item> </el-col> <el-col :span="6" :class="{ mt10: getTextWidth(poDetail.description) > 34 }"> <el-form-item style="margin-left: 20px" label="单位"><span>{{ poDetail.purchaseUOM }}</span></el-form-item> </el-col> </el-row> </el-form> </div> </div>
<!-- Step 2: 收货明细 --> <div v-if="processFlag === 2"> <el-form label-position="top" class="form-section" style="margin: 5px;"> <el-row :gutter="20"> <el-col :span="12"><el-form-item label="PO号码"><el-input v-model="recvItem.orderNo" disabled /></el-form-item></el-col> <el-col :span="12"><el-form-item label="行号/下达号"><el-input v-model="displayLineWdr" disabled /></el-form-item></el-col> <el-col :span="12"><el-form-item label="商品编码"><el-input v-model="recvItem.partNo" disabled /></el-form-item></el-col> <el-col :span="12"><el-form-item label="计量单位"><el-input v-model="recvItem.purchaseUOM" disabled /></el-form-item></el-col> <el-col :span="24"><el-form-item label="商品名称"><el-input v-model="recvItem.description" disabled /></el-form-item></el-col> <el-col :span="12"><el-form-item label="订单数量"><el-input v-model="recvItem.purchaseQty" disabled /></el-form-item></el-col> <el-col :span="12"><el-form-item label="待收数量"><el-input v-model="recvItem.qtyToReceive" disabled /></el-form-item></el-col> <el-col :span="12"> <el-form-item label="此次接收数量"> <el-input v-model="recvItem.transQty" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label=" "><!-- <el-button type="text" @click.stop="handlingUnitStep" :disabled="recvItem.needHandlingUnit !== 'Y'" :class="{ 'disabled-button': recvItem.needHandlingUnit !== 'Y' }" style="font-size: 16px" size="small">包装记录</el-button>--> <el-button type="text" @click.stop="handlingUnitStep" style="font-size: 16px" size="small">包装记录</el-button> </el-form-item> </el-col> <el-col :span="12"><el-form-item label="制造日期"> <el-date-picker v-model="recvItem.manufactureDate" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" placeholder="选择制造日期" style="width: 100%" inputmode="none" autocomplete="off" autocorrect="off" disabled spellcheck="false" /> </el-form-item></el-col> <el-col :span="12"><el-form-item label="供应商批次"> <el-input v-model="recvItem.supplierBatchNo" disabled placeholder="请输入供应商批次" /> </el-form-item></el-col> <el-col :span="12"><el-form-item label="WDR"> <el-input v-model="recvItem.wdr" placeholder="请输入WDR" /> </el-form-item></el-col> <el-col :span="12"><el-form-item label="到达日期"> <el-date-picker v-model="recvItem.arrivalDate" type="date" format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择到达日期" style="width: 100%" inputmode="none" autocomplete="off" autocorrect="off" spellcheck="false" /> </el-form-item></el-col> <el-col :span="12"><el-form-item label="库位"><el-input v-model="recvItem.locationNo" placeholder="请输入库位" @blur="validateLocation" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="批号"><el-input v-model="recvItem.batchNo" placeholder="请输入批号" /></el-form-item></el-col> <el-col :span="8" style="margin-top: 10px"><el-form-item><el-button type="text" style="font-size: 16px;margin-left: 30px" @click="processFlag = 1">回退</el-button></el-form-item></el-col> <el-col :span="8" style="margin-top: 10px"><el-form-item><el-button type="text" style="font-size: 16px;margin-left: 20px" @click="receivePo">保存</el-button></el-form-item></el-col> <el-col :span="8" style="margin-top: 10px"><el-form-item><el-button type="text" style="font-size: 16px;margin-left: 10px" @click="$router.push('/')">退出</el-button></el-form-item></el-col> </el-row> </el-form> </div>
<!-- Step 3: 包装记录 --> <div v-if="processFlag === 3"> <el-form label-position="top" class="form-section" style="margin: 5px;"> <el-row :gutter="20"> <el-col :span="12"><el-form-item label="商品编码"><el-input v-model="recvItem.partNo" disabled /></el-form-item></el-col> <el-col :span="12"><el-form-item label="计量单位"><el-input v-model="recvItem.purchaseUOM" disabled /></el-form-item></el-col> <el-col :span="24"><el-form-item label="商品名称"><el-input v-model="recvItem.description" disabled /></el-form-item></el-col> <el-col :span="8"><el-form-item label="单包装数量"><el-input v-model="hanlingItem.perQty" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="包装数"><el-input v-model="hanlingItem.packageQty" /></el-form-item></el-col> <el-col :span="8" style="margin-top: 24px"><el-form-item> <el-button type="text" @click="createHandlingUnit" style="font-size: 16px">创建</el-button></el-form-item></el-col> <el-table :data="handlingUnit" :row-style="{ height: '30px' }" style="width: 94%; margin-left: 10px;" highlight-current-row> <el-table-column prop="code" label="序号" /> <el-table-column prop="packageQty" label="包装数" width="80" /> <el-table-column prop="perQty" label="单包装数量" width="100" /> <el-table-column label="操作"> <template slot-scope="scope"> <a @click="removeItem(scope.$index)">删除</a> </template> </el-table-column> </el-table> <el-col :span="24"><el-form-item><span>合计</span><span style="margin-left: 38%">{{ totalQty }}</span></el-form-item></el-col> <el-col :span="12"><el-form-item><el-button type="text" @click="processFlag = 2" style="font-size: 18px;margin-left: 60px">回退</el-button></el-form-item></el-col> <el-col :span="12"><el-form-item><el-button type="text" @click="processFlag = 2" style="font-size: 18px;">确定</el-button></el-form-item></el-col> </el-row> </el-form> </div> </div> </div> </div></template>
<script>import { getPoList, receivePo, printLabel, getNextItemNo, validateLocationForReceiveCase } from "@/api/po/po.js";
export default { data() { return { processFlag: 1, scanCode: '', poList: [], recvItem: {}, handlingUnit: [], hanlingItem: { code: '', qty: '', perQty: '', packageQty: '' }, site:localStorage.getItem('site'), warehouseId:localStorage.getItem('selectedWarehouse'), fullscreenLoading: false, // 控制全屏loading
loadingText: '加载中...' // 动态loading文本
}; }, computed: { totalQty() { const sum = this.handlingUnit.reduce((sum, item) => sum + Number(item.qty), 0); this.recvItem.transQty = sum; return sum; }, huKey() { return `hu_${this.recvItem.poNumber}_${this.recvItem.lineNo}`; }, displayLineWdr() { return `${this.recvItem.lineNo || ''}/${this.recvItem.wdr || '*'}`; } }, methods: { // 计算“显示宽度”
getTextWidth(text) { if (!text) return 0 let len = 0 for (let char of text) { // 中文、全角符号
if (/[\u4e00-\u9fa5\u3000-\u303F\uFF00-\uFFEF]/.test(char)) { len += 2 } else { len += 1 } } return len }, handleBack() { if (this.processFlag === 1) this.$router.back(); else if (this.processFlag === 3) this.processFlag = 2; else this.processFlag = 1; }, searchPoList() { if (!this.scanCode) return this.poList = [];
// 开始搜索时显示loading
this.loadingText = '搜索中...'; this.fullscreenLoading = true;
getPoList({ poNumber: this.scanCode,site: this.site }).then(({ data }) => { if (data.code === 0) { this.poList = data.rows } else { this.$message.error(data.msg || '操作失败'); } // 搜索完成后让输入框失去焦点
this.$nextTick(() => { if (this.$refs.scanCodeRef) { this.$refs.scanCodeRef.blur(); } }); }).catch(error => { console.error('搜索失败:', error); this.$message.error('搜索失败,请重试'); }).finally(() => { // 搜索完成后关闭loading
this.fullscreenLoading = false; }); }, async recvLine(row) { if (row.authorizationRequired=='TRUE') { return this.$message.warning("该采购订单需要审核,无法接收"); } if (row.receiveCaseDB!='INVDIR' && row.receiveCaseDB!='QAINV' && row.receiveCaseDB!='ARRINV') { return this.$message.warning("该采购订单行的收货方式为"+row.receiveCase+",无法接收"); } if (row.poStatus === 'Stopped' || row.poStatus === 'Closed' || row.poStatus === 'Cancelled' || row.poStatus === 'Planned') { return this.$message.warning("该采购订单状态为"+row.poStatus+",无法接收"); } if (row.status === 'Stopped' || row.status === 'Closed' || row.status === 'Cancelled') { return this.$message.warning("该采购订单行状态为"+row.status+",无法接收"); } if (row.convFactor !== 1) { return this.$message.warning("采购计量单位和库存计量单位不一致,无法接收"); }
// 获取下一个itemNo
let nextItemNo = 1; try { const { data } = await getNextItemNo({ orderNo: row.orderNo, lineNo: row.lineNo, releaseNo: row.releaseNo || '' }); if (data.code === 0) { nextItemNo = data.data; } } catch (error) { console.error('获取itemNo失败:', error); // 失败时使用默认值1
}
this.recvItem = { ...row, poNo: row.orderNo || this.scanCode, dueinQty: row.qtyToReceive || row.invQtyToReceive, transQty: '', itemNo: nextItemNo, batchNo: row.orderNo+'-'+row.lineNo+'-'+row.releaseNo+'-'+nextItemNo, deliveryDate: row.plannedDeliveryDate || '', arrivalDate: this.getCurrentDate(), supplierBatchNo: '', wdr:"*" }; this.processFlag = 2; }, // 获取当前日期
getCurrentDate() { const now = new Date(); return now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0') + ' ' + String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0') + ':' + String(now.getSeconds()).padStart(2, '0'); }, handlingUnitStep() { this.processFlag = 3; const saved = localStorage.getItem(this.huKey); this.handlingUnit = saved ? JSON.parse(saved) : []; }, createHandlingUnit() { const { perQty, packageQty } = this.hanlingItem; if (!perQty || !packageQty || isNaN(perQty) || isNaN(packageQty)) { return this.$message.warning("请填写有效的包装信息"); } const qty = parseFloat(perQty) * parseInt(packageQty); const code = String(this.handlingUnit.length + 1); const newItem = { ...this.hanlingItem, qty, code }; this.handlingUnit.push(newItem); localStorage.setItem(this.huKey, JSON.stringify(this.handlingUnit));
// 创建HU后清空包装数和单包装数量
this.hanlingItem.perQty = ''; this.hanlingItem.packageQty = ''; }, removeItem(index) { this.handlingUnit.splice(index, 1); localStorage.setItem(this.huKey, JSON.stringify(this.handlingUnit)); }, // 清除所有handlingUnit缓存
clearAllHandlingUnitCache() { this.hanlingItem = { code: '', qty: '', perQty: '', packageQty: '' }; const keys = Object.keys(localStorage); keys.forEach(key => { if (key.startsWith('hu_')) { localStorage.removeItem(key); } }); }, // 校验库位
async validateLocation() { if (!this.recvItem.locationNo || !this.recvItem.receiveCaseDB) { return; }
try { const { data } = await validateLocationForReceiveCase({ site: this.site, locationId: this.recvItem.locationNo, receiveCaseDB: this.recvItem.receiveCaseDB });
if (data.code !== 0) { this.$message.error(data.msg || '库位校验失败'); // 清空库位输入
this.recvItem.locationNo = ''; } } catch (error) { console.error('库位校验失败:', error); this.$message.error('库位校验失败,请重试'); // 清空库位输入
this.recvItem.locationNo = ''; } }, async receivePo() { if (this.fullscreenLoading) return; // 防止重复点
this.loadingText = '提交中...'; this.fullscreenLoading = true; const item = this.recvItem; if (!item.transQty || !item.locationNo || !item.batchNo) { this.fullscreenLoading = false; return this.$message.error("请填写完整信息"); }
// 提交前再次校验库位
try { const { data: validationData } = await validateLocationForReceiveCase({ site: this.site, locationId: item.locationNo, receiveCaseDB: item.receiveCaseDB });
if (validationData.code !== 0) { this.fullscreenLoading = false; return this.$message.error(validationData.msg || '库位校验失败'); } } catch (error) { console.error('库位校验失败:', error); this.fullscreenLoading = false; return this.$message.error('库位校验失败,请重试'); }
// 构建符合服务端TransDetailDto结构的数据
const receiveData = { // 基本字段
site: this.site, warehouseId: this.warehouseId, partNo: item.partNo, partDesc: item.description, transQty: item.transQty, batchNo: item.batchNo, locationNo: item.locationNo, itemNo: item.itemNo, wdr: item.wdr || '*', deliveryDate: item.deliveryDate, arrivalDate: item.arrivalDate, supplierBatchNo: item.supplierBatchNo, samplePercent: item.samplePercent || 0, sampleQty: item.sampleQty || 0, // PO相关字段
poNo: item.poNumber || item.poNo, orderNo: item.orderNo, lineNo: item.lineNo, releaseNo: item.releaseNo, receiptNo: item.receiptNo, orderRef1: item.orderNo, supplierNo: item.supplierNo, purchaseUOM: item.purchaseUOM, receiveCase: item.receiveCase, receiveCaseDB: item.receiveCaseDB, inventoryPartDB: item.inventoryPartDB, // 业务控制字段
needHandlingUnit: item.needHandlingUnit , needCheck: item.needCheck , warehouseType: item.warehouseType , // 日期字段
manufactureDate: item.manufactureDate, // 处理单元列表
handlingUnitList: this.handlingUnit.map(hu => ({ perQty: hu.perQty, packageQty: hu.packageQty })) }; receivePo(receiveData).then(({ data }) => { if (data.code === 0) { this.$message.success("操作成功"); this.clearAllHandlingUnitCache(); this.printViaServer(data.data,item.needCheck); // 调用打印
this.processFlag = 1; this.scanCode = ''; this.poList = []; this.recvItem = {}; this.handlingUnit = []; } else { this.$message.error(data.msg || '操作失败'); } }).catch(error => { console.error('接收失败:', error); this.$message.error('网络错误,请重试'); }).finally(() => { this.fullscreenLoading = false; // 结束后关闭loading
}); }, /** * 通过服务器打印 */ async printViaServer(receiptNo,needCheck) { this.$emit('print-start') try { const printRequest = { reportId: this.reportId, zplCode: this.zplCode, paperSize: this.paperSize, orientation: this.orientation, dpi: this.dpi, userId: localStorage.getItem('userName'), username: localStorage.getItem('userName'), site: localStorage.getItem('site'), receiptNo: receiptNo, needCheck:needCheck, printLabel:"BIL标签" } const { data } = await printLabel(printRequest) if (data.code === 200) { this.$message.success(`打印任务已发送!`) } } catch (error) { console.error('服务器打印失败:', error) this.$message.error(`打印失败: ${error.message || error}`) } }, }, mounted() { this.$nextTick(() => this.$refs.scanCodeRef.focus()); },
};</script>
<style scoped>.mt10 { margin-top: 10px;}.scan-box input { width: 100%; padding: 12px; font-size: 16px;}.item-list { flex: 1; overflow-y: auto; margin: 10px 0; border: 1px solid rgba(200, 200, 200, 0.8);}.item-list span { color: #000; font-size: 15px;}.bottom-line-row { border-bottom: 1px solid rgba(200, 200, 200, 0.8);}.recvButton { font-size: 16px; border-radius: 3px; color: #17b3a3;}.item-list .el-row { cursor: pointer; transition: background 0.3s;}.item-list .el-row:hover { background: #f5f7fa;}.disabled-button { color: #ccc !important; cursor: not-allowed !important;}.form-section >>> .el-col { margin-bottom: 12px;}.status-bar { display: flex; justify-content: space-between; align-items: center; background: #17b3a3; color: white;}
/* 自定义loading样式 */.pda-container >>> .el-loading-mask { background-color: rgba(255, 255, 255, 0.3) !important;}
.pda-container >>> .el-loading-spinner { margin-top: -25px;}
.pda-container >>> .el-loading-spinner .circular { width: 35px; height: 35px;}
.pda-container >>> .el-loading-text { color: #17b3a3 !important; font-size: 14px; font-weight: 500; margin-top: 10px;}</style>
|