<template> <view> <u-popup mode="bottom" v-model="show"> <view class=""> <view class="popup_box"> <view class="pop_title uni-flex space-between"> <view class="" style="font-size: 35rpx"> 扫描箱码 </view> <view class=""> <image class="fr icons_scan_close" src="/static/icons/icons_scan_close.svg" @click="closeScanPopup()"> </image> </view> </view> <view class="uni-flex uni-row" style="align-items: center; background-color: #fff; margin-left: 20rpx; margin-right: 20rpx; margin-top: 8rpx; border-radius: 8rpx"> <view class="uni-center" style="width: 25%; font-size: 35rpx"> 来源库位 </view> <view class="" style="width: 75%; padding: 8rpx"> <uni-combox class="my-combox" :candidates="fromLocationList" v-model="fromLocationCode" placeholder="请选择库位" @confirm="fromLocationUpdate" :inputStyle="inputStyleObject"></uni-combox> </view> </view> <view class=""> <view class=""> <win-com-scan ref="comscan" placeholder="箱标签" @getResult="onScan" :clearResult="true" headerType="HPQ,HMQ" :isShowHistory="false"> </win-com-scan> <view style="width: 100%"> <view style="width: 100%" v-if="issueRecord.length > 0"> <view class="uni-flex uni-row space-between u-col-center"> <view class="" style="padding: 10rpx"> 历史记录 </view> <view class="" style="padding-right: 10rpx"> <u-icon :name="expendIcon" size="35rpx" @click="expands()"></u-icon> </view> </view> <u-line class="line_color" style="padding-top: 10rpx; padding-bottom: 20rpx"> </u-line> <scroll-view scroll-y="true" class="scroll-view" v-if="expand && issueRecord.length > 0"> <u-swipe-action :show="item.show" :index="index" v-for="(item, index) in issueRecord" :key="index" :options="scanOptions" bg-color="rgba(255,255,255,0)" @click="(...event) => swipeClick($event, item)"> <view style="padding: 0px 10px"> <balance :dataContent="item" :isShowFromLocation="false" :isShowStdPack="false"></balance> </view> </u-swipe-action> </scroll-view> </view> </view> </view> </view> </view> </view> </u-popup> <balance-select ref="balanceSelectRef" @onSelectItem="selectBalanceItem"></balance-select> <com-message ref="comMessageRef" /> <balance-qty-edit ref="balanceQtyEditRef" @confirm="confirm" :isShowStatus="true"></balance-qty-edit> <!-- 模拟扫描功能 --> <!-- <win-com-scan v-show="false" ref="comscansimulate" placeholder="箱标签" @getResult="onScan" :clearResult="true" headerType="HPQ,HMQ" :isShowHistory="false"> </win-com-scan> --> </view> </template> <script setup lang="ts"> import { ref, getCurrentInstance, nextTick, onMounted } from 'vue' import winComScan from '@/mycomponents/scan/winComScan.vue' import balance from '@/mycomponents/balance/balance.vue' import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue' import balanceSelect from '@/mycomponents/balance/balanceSelect.vue' import { getDetailOption, getDetailEditRemoveOption } from '@/common/array.js' import { getWorkShopLineStation, getBalanceByFilter,getBalanceByParams } from '@/api/request2.js' import { uniqueArray } from '@/common/basic.js' import { calc } from '@/common/calc.js' import { getBalanceByManagementPrecision } from '@/common/balance.js' import { getDirectoryItemArray } from '../../../common/directory.js' import { getLabelInfo } from '@/common/label.js' const { proxy } = getCurrentInstance() const props = defineProps({ title: { type: String, default: '' } }) const dataContent = ref({}) const jobContent = ref({}) const expendIcon = ref('arrow-down') const show = ref(false) const scanList = ref([]) const toLocation = ref(null) const toLocationCode = ref('') const fromLocationList = ref([]) const fromLocationCode = ref('') const fromLocation = ref(null) const issueRecord = ref([]) // 发料历史 const expand = ref(true) const scanOptions = ref({}) const editItem = ref({}) const positionInfo = ref('请选择位置') const positionList = ref([]) const defaultValueList = ref([]) const fromInventoryStatuses = ref('') const packageInfo = ref({}) const label = ref({}) const inputStyleObject = ref({ fontSize: '100rpx' }) const bussinessCode = ref('Issue') const toLocationCombox = ref() const comscansimulate = ref() const comMessageRef = ref() const detailOptions = ref([]) const comscan = ref() const balanceSelectRef = ref() const balanceQtyEditRef = ref() onMounted(() => { detailOptions.value = getDetailOption() scanOptions.value = getDetailEditRemoveOption() }) const openScanPopupForJobSimulate = (content, jobcontentParams, scanMessage) => { issueRecord.value = [] dataContent.value = content jobContent.value = jobcontentParams initData() getLabelInfo(scanMessage, 'HPQ,HMQ', (callback) => { if (callback.success) { onScan(callback) } else { showErrorMessage(callback.message, (res) => {}) } }) } const openScanPopup = (content, jobcontentParams) => { issueRecord.value = [] dataContent.value = content jobContent.value = jobcontentParams initData() // this.positionInfo = this.jobContent.workShopCode + "-" + this.jobContent.subList[0].productionLineCode + // "-" + this.jobContent.subList[0].workStationCode setTimeout((res) => { show.value = true }, 500) } const closeScanPopup = () => { show.value = false emit('closeScan') // 清除数据,恢复默认值 // Object.assign(this.$data, this.$options.data()); } const initData = () => { fromLocationList.value = [] if (dataContent.value != null) { fromInventoryStatuses.value = jobContent.value.outInventoryStatuses toLocation.value = dataContent.value[0] toLocationCode.value = dataContent.value[0].toLocationCode fromLocationList.value = getFromLocationList() } } const showBalanceSelect = (items) => { balanceSelectRef.value.openPopup(items) } const getFromLocationList = () => { let list = [] dataContent.value.forEach((location) => { location.Items.forEach((item) => { item.Locations.forEach((f) => { const item = list.find((l) => l == f.fromLocationCode) if (item == undefined) { list.push(f.fromLocationCode) } }) }) }) // 去掉重复库位 list = uniqueArray(list) fromLocationCode.value = list[0] return list } const fromLocationUpdate = (fromlocation) => { const location = fromLocationList.value.find((r) => r == fromlocation) if (location == undefined) { fromLocationCode.value = '' showErrorMessage(`发料库位【${fromlocation}】不存在`) } } const onScanResult = (result) => { try { if (fromLocationCode.value == '') { showErrorMessage('请选择来源库位', (res) => { toLocationCombox.value.onFocus() }) return } const packageInfoParams = result.package const { itemCode } = result.label const packingCode = result.label.packingNumber const lot = result.label.batch const item = toLocation.value.Items.find((r) => r.itemCode == itemCode) if (item == undefined) { showErrorMessage(`未查找到物料【${itemCode}】的发料明细`, (res) => { getfocus() }) return }else { queryBalance(result) } // getBalance(result.label, packageInfoParams, (balances) => { // packageInfo.value = packageInfoParams // // 扫描的是外包装 // const s = '' // if (!result.package.parentNumber) { // if (balances.list.length == 0) { // showErrorMessage('未查找到该包装的库存信息,请重新扫描') // } else { // const newBalances = balances.list.filter((b) => b.locationCode == fromLocationCode.value) // if (newBalances.length == 0) { // showErrorMessage('未查找到该包装的库存信息,请重新扫描') // } else if (newBalances.length == 1) { // const balance = newBalances[0] // afterGetBalance(result.label, balance, packageInfoParams) // } else { // showBalanceSelect(newBalances) // } // } // } else { // // 扫描的是小包装 // if (balances.list.length == 0) { // showErrorMessage('未查找到该包装的库存信息,请重新扫描') // } else { // // 小包装库存 // const subPackitems = balances.list.filter((r) => r.packingNumber == packageInfoParams.number) // // 外包装库存 // const subParentPackitems = balances.list.filter((r) => r.packingNumber == packageInfoParams.parentNumber && r.locationCode == fromLocationCode.value) // // // 小包装没有库存, // if (subPackitems.length == 0) { // // 外包装有库存,出库后剩余库存未转换为出库包装规格 // // if (subParentPackitems.length > 0) { // if (subParentPackitems.length == 1) { // const balance = subParentPackitems[0] // balance.qty = packageInfoParams.qty // afterGetBalance(result.label, balance, packageInfo) // } else { // showBalanceSelect(subParentPackitems) // } // } else { // showErrorMessage(`按外包装【${packageInfoParams.parentNumber}】和子包装【${packageInfoParams.number}】都未查找到库存余额`) // } // } else { // let locationCode = fromLocationCode.value // if (balances.list == 1) { // locationCode = balances.list[0].locationCode // } else { // const manyBlances = balances.list.filter((r) => r.locationCode != fromLocationCode.value) // if (manyBlances.length > 0) { // locationCode = manyBlances[0].locationCode // } // } // showErrorMessage(`该包装【${packageInfoParams.number}】在库位【${locationCode}】已经有库存余额,请重新扫描`) // } // } // } // uni.hideLoading() // }) } catch (e) { showErrorMessage(e.stack) uni.hideLoading() } } const queryBalance = (result)=>{ var params = { itemCode: result.package.itemCode, batch: result.label.batch, packingNumber: result.label.packingNumber, parentPackingNumber: result.package.parentNumber, inventoryStatus: jobContent.value.outInventoryStatuses.split(','), areaType:jobContent.value.fromAreaTypes.split(','), bussinessCode:jobContent.value.businessType } uni.showLoading({ title: '查询中', mask: true }) getBalanceByParams(params).then(res => { if (res.data.length == 0) { var status = getInventoryStatusDesc(params.inventoryStatus) var areaType = getListLocationAreaTypeDesc(params.areaType) var hint = "按物料号 [" + params.itemCode + "] <br>" + "包装号 [" + params.packingNumber + "] <br>" + "批次 [" + params.batch + "] <br>" + "状态 [" + status + "] <br>" + "库区 [" + areaType + "] <br>" + "未查找到库存余额" this.showErrorMessage(hint) } else if (res.data.length == 1) { result.balance = res.data[0] if (result.label.packingNumber != result.balance.packingNumber) { result.balance.lableQty = result.label.qty } this.afterGetBalance(result.label, result.balance, result.package); } else { //多条记录 this.$refs.balanceSelect.openPopup(res.data); } uni.hideLoading() }).catch(error => { uni.hideLoading() this.showErrorMessage(error) }) } const getBalance = (label, packageInfoParams, callback) => { const filters = [] if (packageInfoParams.parentNumber) { const packingNumber = `${packageInfoParams.parentNumber},${label.packingNumber}` filters.push({ column: 'packingNumber', action: 'in', value: packingNumber }) } else { filters.push({ column: 'packingNumber', action: '==', value: label.packingNumber }) } filters.push({ column: 'itemCode', action: '==', value: label.itemCode }) filters.push({ column: 'batch', action: '==', value: label.batch }) if (fromInventoryStatuses.value != null && fromInventoryStatuses.value != '') { filters.push({ column: 'inventoryStatus', action: 'in', value: fromInventoryStatuses.value }) } const params = { filters, pageNo: 1, pageSize: 100 } getBalanceByFilter(params) .then((res) => { callback(res.data) }) .catch((err) => { showErrorMessage(err.message) }) } const onScan = (result) => { if (!result.package) { showErrorMessage(`扫描数据错误[${result.label.code}]`, (res) => { getfocus() }) return } if (toLocation.value && result.package.packUnit) { const item = toLocation.value.Items.find((r) => r.itemCode == result.package.itemCode) if(!item){ showErrorMessage('扫描物料代码不属于该任务'); return } if (result.package.packUnit !== item.packUnit) { comMessageRef.value.showQuestionMessage(`扫描物料包装【${result.package.packUnit}】与任务推荐包装规格【${item.packUnit}】不一致.是否要继续发料?`, (res) => { if (res) { onScanResult(result) } }) } else { onScanResult(result) } } } const onScanResult1 = (result) => { try { if (fromLocationCode.value == '') { showErrorMessage('请选择来源库位', (res) => { toLocationCombox.value.onFocus() }) return } label.value = result.package // let packageInfo = result.package; const { itemCode } = result.label const packingCode = result.label.packingNumber const lot = result.label.batch const item = toLocation.value.Items.find((r) => r.itemCode == itemCode) if (item == undefined) { showErrorMessage(`未查找到物料【${itemCode}】的发料明细`, (res) => { getfocus() }) return } // 查找库存信息 proxy.$modal.loading('加载中') getBalanceByManagementPrecision(result.label, fromLocationCode.value, fromInventoryStatuses.value, (balanceRes) => { if (balanceRes.success) { if (balanceRes.data.list.length == 0) { showErrorMessage(`在来源库位[${fromLocationCode.value}],未查找到该包装的库存记录`, (res) => { packGetFocus() }) } else if (balanceRes.data.list.length == 1) { const balance = balanceRes.data.list[0] afterGetBalance(result.label, balance, packageInfo.value) } else { showBalanceSelect(balanceRes.data.list) } } else { showErrorMessage(balanceRes.message) } uni.hideLoading() }) } catch (e) { showErrorMessage(e.stack) uni.hideLoading() } } const selectBalanceItem = (balance) => { afterGetBalance(label.value, balance, packageInfo.value) } const afterGetBalance = (label, balance, packageInfo) => { try { const { itemCode } = label const packingCode = label.packingNumber const lot = label.batch const item = toLocation.value.Items.find((r) => r.itemCode == itemCode) const fromLocation = item.Locations.find((l) => l.fromLocationCode == fromLocationCode.value) if (fromLocation != undefined) { const batch = fromLocation.Batchs.find((r) => r.batch == lot) if (batch != undefined) { if (batch.Records == undefined) { batch.Records = [] } const record = batch.Records.find((r) => r.packingNumber == packingCode) if (record == undefined) { // 如果有推荐箱码 if (batch.Recommends.length > 0) { const recommend = batch.Recommends.find((r) => r.packingNumber == packingCode) if (recommend != undefined) { addRecord(batch, label, balance, packageInfo) } else { // 允许修改箱码 if (jobContent.value.allowModifyPackingNumber == 'TRUE') { addRecord(batch, label, balance, packageInfo) } else { showErrorMessage(`未查找到该箱码【${packingCode}】的明细`, (res) => { getfocus() }) } } } else { addRecord(batch, label, balance, packageInfo) } emit('afterScan') } else { showErrorMessage(`箱码【${packingCode}】已经扫描,请继续扫描下一箱`, (res) => { getfocus() }) } } else if (jobContent.value.allowModifyBatch == 'TRUE') { showQuestionMessage(`在【${fromLocationCode.value}】库位下,未查找到批次【${lot}】的发料明细,是否要继续发料?`, (res) => { if (res) { const batch = createBatchInfo(label, balance, packageInfo) // 新增加的批次赋值details if (fromLocation.Batchs.length > 0) { batch.detail = fromLocation.Batchs[0].detail } fromLocation.Batchs.unshift(batch) emit('afterScan') } }) } else { showErrorMessage(`未查找到批次【${lot}】的发料明细`, (res) => { getfocus() }) } } else { showErrorMessage(`未查找到推荐库位【${fromLocationCode.value}】的发料明细`, (res) => { getfocus() }) } } catch (e) { showErrorMessage(e.stack, (res) => { getfocus() }) } } const createBatchInfo = (data, balance, packageInfo) => { const batch = { batch: data.batch, qty: 0, uom: data.uom, handleQty: Number(data.qty), Records: [] } const record = creatRecord(data, balance, packageInfo) batch.Records.push(record) issueRecord.value.unshift(record) return batch } const creatRecord = (label, balance, packageInfo) => { balance.packQty = packageInfo.packQty balance.packUnit = packageInfo.packUnit const record = { scaned: true, itemCode: label.itemCode, packingNumber: label.packingNumber, parentPackingNumber: packageInfo.parentNumber, batch: label.batch, qty: Number(balance.qty), // qty: Number(label.qty) > Number(balance.qty) ? Number(balance.qty) : Number(label.qty), uom: balance.uom, inventoryStatus: balance.inventoryStatus, balance, toLocationCode: toLocationCode.value, supplierCode: label.supplierCode, packUnit: packageInfo.packUnit, packQty: packageInfo.packQty } return record } const calcBatchHandleQty = (batch) => { let handleQty = 0 batch.Records.forEach((res) => { handleQty = calc.add(handleQty, res.qty) }) batch.handleQty = handleQty } const addRecord = (batch, label, balance, packageInfo) => { const record = creatRecord(label, balance, packageInfo) batch.Records.push(record) issueRecord.value.unshift(record) calcBatchHandleQty(batch) getfocus() } const getfocus = () => { if (!comscan.value) { comscan.value.getfocus() } } const losefocus = () => { if (comscan.value != undefined) { comscan.value.losefocus() } } const expands = () => { expand.value = !expand.value expendIcon.value = expand.value == true ? 'arrow-down' : 'arrow-up' } // const swipeClick = (e, item, index) => { // if (e.content.text == '详情') { // this.detail(item) // } else if (e.content.text == '编辑') { // this.edit(item) // } else if (e.content.text == '移除') { // this.remove(item, index) // } // } const swipeClick = (params, item) => { const { text } = scanOptions.value[params[1]] if (text == '详情') { detail(item) } else if (text == '编辑') { edit(item) } else if (text == '库位') { showLocation(item) } else if (text == '移除') { remove(item) } } const edit = (item) => { editItem.value = item // item.balance.balanceQty = item.balance.qty; item.balance.balanceQty = item.balance.qty balanceQtyEditRef.value.openEditPopup(item.balance, item.qty) } const detail = (item) => { showItem.value = item receiptHint.value.openScanPopup() } const remove = (record, index) => { showQuestionMessage('确定移除扫描信息?', (res) => { if (res) { record.qty = 0 issueRecord.value.splice(index, 1) const item = toLocation.value.Items.find((r) => r.itemCode == record.itemCode) if (item != undefined) { item.Locations.forEach((l) => { const batch = l.Batchs.find((b) => b.packingNumber == record.packingNumber && b.batch == record.batch) if (batch && batch.Records && batch.Records.length > 0) { const rIndex = batch.Records.findIndex((r) => r.packingNumber == record.packingNumber && r.batch == record.batch) batch.Records.splice(rIndex, 1) } }) } emit('updateData', item) } }) } const packGetFocus = () => { if (comscan.value) { comscan.value.getfocus() } } const packLoseFocus = () => { if (comscan.value) { comscan.value.losefocus() } } const showMessage = (message, callback) => { setTimeout((r) => { packLoseFocus() comMessageRef.value.showMessage(message, callback) }) } const showErrorMessage = (message, callback) => { setTimeout((r) => { packLoseFocus() comMessageRef.value.showErrorMessage(message, callback) }) } const showQuestionMessage = (message, callback) => { setTimeout((r) => { packLoseFocus() comMessageRef.value.showQuestionMessage(message, callback) }) } const confirm = (val) => { editItem.value.qty = Number(val) emit('updateData', editItem.value) } const cancle = () => { closeScanPopup() } // 传递给父类 const emit = defineEmits(['updateData', 'closeScan', 'afterScan']) defineExpose({ openScanPopup, closeScanPopup, openScanPopupForJobSimulate }) </script> <style lang="scss"> button { border: none; } button::after { border: none; } .scroll-view { overflow-y: scroll; height: auto; max-height: 300rpx; padding: 10rpx; } </style>