## **DFI友通资讯操作站** #### **项目介绍** 客户为台湾厂商,通过操作站结合WMS及AGV无人车实现智慧仓储物流系统。 今年4月开发重构第二个版本,目前已完成。 #### **主要工作** 负责开发前端操作站界面和后台功能。 #### **主要功能** 繁体中文及英语多语言功能,业务功能包括:派單,有單上架,無單上架,揀貨,條碼綁定,貨架報表,盤點等功能。 其中包括ASRS 防潮柜/线边仓版本。 #### **技术栈** Vue2 Vuetify RabbitMQ 订阅 .NetCore MySql NHibernate #### **预览** 现场操作视频 [WeChat_20231017211753.mp4](WeChat_20231017211753.mp4 ':include :type=video controls width=100%') 派单界面 ![Alt text](image-10.png) 拣货界面 ![Alt text](image-11.png) 上架界面 ![Alt text](image-12.png) #### **代码片段(业务封装类)** ```JavaScript import $EventBus from '@/utils/$EventBus' const NO_ITEM = (text = '', $vuetify) => { let message = $vuetify.lang.t('$vuetify.common.message.no_item') return message + ' ' + text } const SHELF_FULL = (text = '', $vuetify) => { let message = $vuetify.lang.t('$vuetify.common.message.shelf_full') return message + ' ' + text } const NOT_FOUND_BARCODE = ($vuetify) => { return $vuetify.lang.t('$vuetify.common.message.not_found_barcode') } const NOT_FOUND_ITEM = ($vuetify) => { return $vuetify.lang.t('$vuetify.common.message.not_found_item') } const NUMBER_OUT = ($vuetify) => { return $vuetify.lang.t('$vuetify.common.message.number_out') } const NOT_FOUND_ORDER = ($vuetify) => { return $vuetify.lang.t('$vuetify.common.message.not_found_order') } const REPEAT_SCAN = ($vuetify) => { return $vuetify.lang.t('$vuetify.common.message.repeat_scan') } //刪除條碼,扣回來 export const deleteBarcodeOutInBin = (barcode, inboundOrderDetail, that) => { return new Promise((resolve, reject) => { let hu_idx = that.currentHuList.findIndex((item) => item.HuId === barcode) if (hu_idx < 0) { $EventBus.$emit('MESSAGE_RECEIVE', { text: NOT_FOUND_BARCODE(that.$vuetify), type: 'ErrorMessages' }) reject() } let barcodeInfo = that.currentHuList[hu_idx] let det_idx = inboundOrderDetail.findIndex((item) => item.Id === barcodeInfo.InboundTaskDetId) if (det_idx < 0) { $EventBus.$emit('MESSAGE_RECEIVE', { text: NOT_FOUND_ORDER(that.$vuetify), type: 'ErrorMessages' }) reject() } let det = inboundOrderDetail[det_idx] det.EntryQty -= barcodeInfo.Qty that.$set(that.inboundOrderInfo.Details, det_idx, det) that.inboundOrderInfo.SumFinishedQty -= barcodeInfo.Qty that.table.deleteRow(barcodeInfo.HuId) that.currentHuList.splice(hu_idx, 1) resolve(barcodeInfo) }) } export const semiProductCartonCheck = (barcodeInfoList, inboundOrderDetail, that) => { let qtys = barcodeInfoList.map((item) => { return item.Qty }) let huMaxQty = qtys.reduce((n, m) => n + m) let old_qtys = that.currentHuList.map((item) => { return item.Qty }) if (huMaxQty > that.inboundOrderInfo.SumUnfinishedQty) { $EventBus.$emit('MESSAGE_RECEIVE', { text: NUMBER_OUT(that.$vuetify), type: 'ErrorMessages' }) return false } inboundOrderDetail = JSON.parse(JSON.stringify(that.inboundOrderDetailsCopy)) for (let i = 0; i < inboundOrderDetail.length; i++) { if (inboundOrderDetail[i].EntryQty === inboundOrderDetail[i].Qty) { continue } for (let j = 0; j < barcodeInfoList.length; j++) { if (inboundOrderDetail[i].ItemCode === barcodeInfoList[j].Item) { if (barcodeInfoList[j].Qty > (inboundOrderDetail[i].Qty - inboundOrderDetail[i].EntryQty)) { continue } if (barcodeInfoList[j].InboundTaskDetId) { continue } inboundOrderDetail[i].EntryQty += barcodeInfoList[j].Qty barcodeInfoList[j].InboundTaskDetId = inboundOrderDetail[i].Id if (inboundOrderDetail[i].ErpLoc !== null && inboundOrderDetail[i].ErpLoc !== '') { barcodeInfoList[j].ErpLoc = inboundOrderDetail[i].ErpLoc } } } if (i === (inboundOrderDetail.length - 1)) { that.itemInfo.item = inboundOrderDetail[i].ItemCode that.itemInfo.qty = inboundOrderDetail[i].Qty that.itemInfo.item_desc = inboundOrderDetail[i].ItemName that.itemInfo.remaining = inboundOrderDetail[i].Qty - inboundOrderDetail[i].EntryQty that.itemInfo.enter_qty = inboundOrderDetail[i].EntryQty } } that.$set(that.inboundOrderInfo, 'Details', inboundOrderDetail) if (old_qtys.length > 0) { that.inboundOrderInfo.SumFinishedQty -= old_qtys.reduce((n, m) => n + m) } that.inboundOrderInfo.SumFinishedQty += qtys.reduce((n, m) => n + m) return true } //條碼邏輯 export const checkPutInBin = (barcodeInfo, inboundOrderDetail, that) => { return new Promise((resolve, reject) => { let hu_idx = that.currentHuList.findIndex((item) => item.HuId === barcodeInfo.HuId) if (hu_idx > -1) { $EventBus.$emit('MESSAGE_RECEIVE', { text: REPEAT_SCAN(that.$vuetify), type: 'ErrorMessages' }) reject() } let matchId = null let matchItem = null // let itemDet = inboundOrderDetail.filter((item,i) => item.ItemCode === barcodeInfo.Item) let itemDet = [] for (let i = 0; i < inboundOrderDetail.length; i++) { if (inboundOrderDetail[i].ItemCode === barcodeInfo.Item) { itemDet.push({ index: i, item: inboundOrderDetail[i] }) } } if (itemDet.length === 0) { $EventBus.$emit('MESSAGE_RECEIVE', { text: NO_ITEM(barcodeInfo.HuId, that.$vuetify), type: 'ErrorMessages' }) reject() } else { for (let i = 0; i < itemDet.length; i++) { if (!matchId) { if (itemDet[i].item.EntryQty < itemDet[i].item.Qty && (itemDet[i].item.Qty - itemDet[i].item.EntryQty) >= barcodeInfo.Qty) { itemDet[i].item.EntryQty += barcodeInfo.Qty that.$set(that.inboundOrderInfo.Details, itemDet[i].index, itemDet[i].item) //set info that.itemInfo.item = itemDet[i].item.ItemCode that.itemInfo.qty = itemDet[i].item.Qty that.itemInfo.item_desc = itemDet[i].item.ItemName that.itemInfo.remaining = itemDet[i].item.Qty - itemDet[i].item.EntryQty that.itemInfo.enter_qty = itemDet[i].item.EntryQty matchId = itemDet[i].item.Id matchItem = itemDet[i].item } } } if (!matchId) { $EventBus.$emit('MESSAGE_RECEIVE', { text: SHELF_FULL(barcodeInfo.HuId, that.$vuetify), type: 'ErrorMessages' }) reject() } else { resolve(matchItem) } } }) } ```