Jelajahi Sumber

库位合并

zh 3 bulan lalu
induk
melakukan
43c2758dbf
1 mengubah file dengan 112 tambahan dan 18 penghapusan
  1. 112 18
      src/views/robot/merge/index.vue

+ 112 - 18
src/views/robot/merge/index.vue

@@ -18,7 +18,7 @@
     <div class="info-table">
     <div class="info-table">
       <div class="table-row">
       <div class="table-row">
         <div class="cell label">源库位</div>
         <div class="cell label">源库位</div>
-        <div class="cell value input-cell">
+        <div class="cell value input-cell source-location-cell">
           <van-search
           <van-search
             ref="sourceLocationInputRef"
             ref="sourceLocationInputRef"
             v-model.lazy="sourceLocation"
             v-model.lazy="sourceLocation"
@@ -68,7 +68,7 @@
       </div>
       </div>
       <div class="table-row">
       <div class="table-row">
         <div class="cell label">目标库位</div>
         <div class="cell label">目标库位</div>
-        <div class="cell value input-cell input-wide">
+        <div class="cell value input-cell input-wide source-location-cell">
           <van-search
           <van-search
             ref="targetLocationInputRef"
             ref="targetLocationInputRef"
             v-model.lazy="productInfo.targetLocationNew"
             v-model.lazy="productInfo.targetLocationNew"
@@ -84,7 +84,7 @@
         <div class="cell value editable" @dblclick="editMoveQty">
         <div class="cell value editable" @dblclick="editMoveQty">
           <template v-if="isEditingMoveQty">
           <template v-if="isEditingMoveQty">
             <van-field
             <van-field
-              v-model="productInfo.moveQty"
+              v-model="productInfo.actualMoveQty"
               type="number"
               type="number"
               autofocus
               autofocus
               @blur="confirmMoveQty"
               @blur="confirmMoveQty"
@@ -92,8 +92,8 @@
             />
             />
           </template>
           </template>
           <template v-else>
           <template v-else>
-            <span>{{ productInfo.moveQty }}</span>
-            <span v-if="!productInfo.moveQty" class="placeholder">双击编辑</span>
+            <span>{{ productInfo.actualMoveQty }}</span>
+            <span class="placeholder">双击编辑</span>
           </template>
           </template>
         </div>
         </div>
       </div>
       </div>
@@ -391,8 +391,7 @@ const onBarcodeEnter = async () => {
     const params = {
     const params = {
       warehouse,
       warehouse,
       barcode: scanBarcode.value,
       barcode: scanBarcode.value,
-      location: sourceLocation.value,
-      locationRegexp: '^(?!STAGE_|SORTATION_).*$'
+      location: sourceLocation.value
     }
     }
 
 
     const res = await getInventory(params)
     const res = await getInventory(params)
@@ -412,7 +411,13 @@ const onBarcodeEnter = async () => {
       productInfo.batchNo = inventoryData.lotNumber
       productInfo.batchNo = inventoryData.lotNumber
       productInfo.productionDate = inventoryData.lotAtt01
       productInfo.productionDate = inventoryData.lotAtt01
       productInfo.expiryDate = inventoryData.lotAtt02
       productInfo.expiryDate = inventoryData.lotAtt02
-      productInfo.moveQty = inventoryData.quantityAvailable + inventoryData.quantityAvailable
+      // 可移库数量
+      const availableQty = inventoryData.quantityAvailable || 0
+      productInfo.moveQty = availableQty
+      // 计算推荐移库数量:取可移库数量和任务推荐数量的最小值
+      const taskRecommendQty = getTaskRecommendQty(sourceLocation.value)
+      productInfo.recommendMoveQty = taskRecommendQty > 0 ? Math.min(availableQty, taskRecommendQty) : availableQty
+      productInfo.actualMoveQty = '' // 用户实际填写数量初始为空
 
 
       scanSuccess()
       scanSuccess()
       showToast('商品信息获取成功')
       showToast('商品信息获取成功')
@@ -452,6 +457,7 @@ const resetExceptBoxCode = () => {
   scanBarcode.value = ''
   scanBarcode.value = ''
   selectedBox.value = null
   selectedBox.value = null
   resetProductInfo()
   resetProductInfo()
+  productInfo.targetLocationNew = '' // 清空目标库位
   scanType.value = 2
   scanType.value = 2
   focusSourceLocationInput()
   focusSourceLocationInput()
 }
 }
@@ -470,6 +476,8 @@ const resetProductInfo = () => {
   productInfo.productionDate = ''
   productInfo.productionDate = ''
   productInfo.expiryDate = ''
   productInfo.expiryDate = ''
   productInfo.moveQty = ''
   productInfo.moveQty = ''
+  productInfo.recommendMoveQty = ''
+  productInfo.actualMoveQty = ''
 }
 }
 
 
 // 加载料箱数据
 // 加载料箱数据
@@ -605,7 +613,9 @@ const productInfo = reactive({
   batchNo: '',
   batchNo: '',
   productionDate: '',
   productionDate: '',
   expiryDate: '',
   expiryDate: '',
-  moveQty: '',
+  moveQty: '', // 可移库数量(库存可用数量)
+  recommendMoveQty: '', // 推荐移库数量(取可移库数量和任务推荐数量的最小值)
+  actualMoveQty: '', // 用户实际填写的移库数量
   targetLocationNew: ''
   targetLocationNew: ''
 })
 })
 
 
@@ -969,15 +979,22 @@ const selectSubLocation = (station: StationItem, sub: SubLocation) => {
 }
 }
 
 
 // 确认选择库位
 // 确认选择库位
-const confirmSelectLocation = () => {
+const confirmSelectLocation = async () => {
   if (currentLocation.recommendType === 'clear') {
   if (currentLocation.recommendType === 'clear') {
     // 推荐清空库位,填入源库位
     // 推荐清空库位,填入源库位
     sourceLocation.value = currentLocation.id
     sourceLocation.value = currentLocation.id
     showLocationPopup.value = false
     showLocationPopup.value = false
     showToast(`已选择源库位: ${currentLocation.id}`)
     showToast(`已选择源库位: ${currentLocation.id}`)
-    // 切换到扫描商品条码
-    scanType.value = 3
-    focusBarcodeInput()
+
+    // 如果有SKU,自动查询库存信息
+    if (currentLocation.sku) {
+      scanBarcode.value = currentLocation.sku
+      await queryInventoryBySku(currentLocation.sku, currentLocation.id)
+    } else {
+      // 切换到扫描商品条码
+      scanType.value = 3
+      focusBarcodeInput()
+    }
   } else {
   } else {
     // 推荐保留库位,填入目标库位
     // 推荐保留库位,填入目标库位
     productInfo.targetLocationNew = currentLocation.id
     productInfo.targetLocationNew = currentLocation.id
@@ -986,6 +1003,79 @@ const confirmSelectLocation = () => {
   }
   }
 }
 }
 
 
+// 根据SKU查询库存信息
+const queryInventoryBySku = async (sku: string, location: string) => {
+  try {
+    showLoadingToast({ message: '查询中...', forbidClick: true })
+
+    const params = {
+      warehouse,
+      barcode: sku,
+      location: location
+    }
+
+    const res = await getInventory(params)
+    closeToast()
+
+    if (res.data && res.data.length > 0) {
+      const inventoryData = res.data[0]
+      // 保存完整的库存数据
+      currentInventoryData.value = inventoryData
+      // 填充商品信息
+      productInfo.targetLocation = location
+      productInfo.stockQty = inventoryData.quantity
+      productInfo.productName = inventoryData.productName
+      productInfo.barcode = inventoryData.barcode || inventoryData.barcode2
+      productInfo.qualityStatus = inventoryData.lotAtt08
+      productInfo.warehouseType = inventoryData.lotAtt05
+      productInfo.batchNo = inventoryData.lotNumber
+      productInfo.productionDate = inventoryData.lotAtt01
+      productInfo.expiryDate = inventoryData.lotAtt02
+      // 可移库数量
+      const availableQty = inventoryData.quantityAvailable || 0
+      productInfo.moveQty = availableQty
+      // 计算推荐移库数量:取可移库数量和任务推荐数量的最小值
+      const taskRecommendQty = getTaskRecommendQty(location)
+      productInfo.recommendMoveQty = taskRecommendQty > 0 ? Math.min(availableQty, taskRecommendQty) : availableQty
+      productInfo.actualMoveQty = '' // 用户实际填写数量初始为空
+
+      scanSuccess()
+      showToast('商品信息获取成功')
+      // 切换到扫描目标库位
+      scanType.value = 4
+      focusTargetLocationInput()
+    } else {
+      scanError()
+      showToast('未找到库存信息')
+      currentInventoryData.value = null
+      resetProductInfo()
+      // 切换到扫描商品条码
+      scanType.value = 3
+      focusBarcodeInput()
+    }
+  } catch (error: any) {
+    closeToast()
+    scanError()
+    showToast(error.message || '查询失败')
+    // 切换到扫描商品条码
+    scanType.value = 3
+    focusBarcodeInput()
+  }
+}
+
+// 获取任务推荐移库数量(从mergeDetails中获取对应源库位的moveQty)
+const getTaskRecommendQty = (location: string): number => {
+  let totalQty = 0
+  mergeDataList.value.forEach(boxDetail => {
+    boxDetail.mergeDetails?.forEach((detail: LocationMergeDetails) => {
+      if (detail.sourceLocation === location && detail.moveQty) {
+        totalQty += detail.moveQty
+      }
+    })
+  })
+  return totalQty
+}
+
 // 呼唤机器人
 // 呼唤机器人
 const callRobot = async () => {
 const callRobot = async () => {
   try {
   try {
@@ -1030,20 +1120,20 @@ const submitMove = () => {
     showToast('请先选择目标库位')
     showToast('请先选择目标库位')
     return
     return
   }
   }
-  if (!productInfo.moveQty || Number(productInfo.moveQty) <= 0) {
+  if (!productInfo.actualMoveQty || Number(productInfo.actualMoveQty) <= 0) {
     scanError()
     scanError()
     showToast('请输入有效的移库数量')
     showToast('请输入有效的移库数量')
     return
     return
   }
   }
-  if (Number(productInfo.moveQty) > Number(productInfo.stockQty)) {
+  if (Number(productInfo.actualMoveQty) > Number(productInfo.moveQty)) {
     scanError()
     scanError()
-    showToast('移库数量不能大于库数量')
+    showToast('移库数量不能大于可移库数量')
     return
     return
   }
   }
 
 
   showConfirmDialog({
   showConfirmDialog({
     title: '移库确认',
     title: '移库确认',
-    message: `${productInfo.barcode}从"${sourceLocation.value}"移动至"${productInfo.targetLocationNew}"共:${productInfo.moveQty}件`
+    message: `${productInfo.barcode}从"${sourceLocation.value}"移动至"${productInfo.targetLocationNew}"共:${productInfo.actualMoveQty}件`
   })
   })
     .then(() => {
     .then(() => {
       const { traceId, lotNum, lotNumber, ownerCode, owner, sku } = currentInventoryData.value || {}
       const { traceId, lotNum, lotNumber, ownerCode, owner, sku } = currentInventoryData.value || {}
@@ -1054,7 +1144,7 @@ const submitMove = () => {
         sku: sku || productInfo.barcode,
         sku: sku || productInfo.barcode,
         lotNum: lotNum || lotNumber || productInfo.batchNo || '',
         lotNum: lotNum || lotNumber || productInfo.batchNo || '',
         warehouse,
         warehouse,
-        quantity: Number(productInfo.moveQty),
+        quantity: Number(productInfo.actualMoveQty),
         toLocation: productInfo.targetLocationNew
         toLocation: productInfo.targetLocationNew
       }
       }
       showLoadingToast({ message: '提交中...', forbidClick: true })
       showLoadingToast({ message: '提交中...', forbidClick: true })
@@ -1173,6 +1263,10 @@ const submitMove = () => {
         }
         }
       }
       }
 
 
+      &.source-location-cell {
+        flex: 2;
+      }
+
       &.editable {
       &.editable {
         cursor: pointer;
         cursor: pointer;
         min-height: 20px;
         min-height: 20px;