Просмотр исходного кода

Merge branch 'recommended-location' into testing

# Conflicts:
#	src/views/inbound/putaway/task/index.vue
zhaohuanhuan 1 месяц назад
Родитель
Сommit
804d28564a

+ 14 - 1
src/api/haikang/index.ts

@@ -1,7 +1,7 @@
 // @ts-ignore
 import request from '@/utils/request'
 // @ts-ignore
-import {getWaitPutawayListType, getRecommendedLocationType,setBindAllocateWallType } from '@/types/haikang'
+import {getWaitPutawayListType, getRecommendedLocationType, getRecommendedLocationTypeNew, setBindAllocateWallType } from '@/types/haikang'
 /**
  * 上架任务列表
  * @param params
@@ -24,6 +24,19 @@ export function getRecommendedLocation(params:getRecommendedLocationType) {
     params
   })
 }
+
+/**
+ * 推荐库位-精准推荐
+ * @param data
+ */
+export function getRecommendedLocationNew(data:getRecommendedLocationTypeNew) {
+  return request({
+    url: '/api/basic/location/resource/getRecommendedLocation',
+    method: 'post',
+    data
+  })
+}
+
 /**
  * 商品绑定分拨墙格口
  * @param data

+ 37 - 0
src/types/haikang.ts

@@ -47,6 +47,43 @@ export interface getRecommendedLocationType {
   [property: string]: any;
 }
 
+/**
+ * 推荐库位查询对象
+ *
+ * LocationRecommendedQO
+ */
+export interface getRecommendedLocationTypeNew {
+  /**
+   * 需排除的库位列表
+   */
+  excludedLocations?: string[];
+  /**
+   * 批次号
+   */
+  lotNum: string;
+  /**
+   * 货主编码
+   */
+  owner: string;
+  /**
+   * 数量
+   */
+  qty: number;
+  /**
+   * 商品SKU
+   */
+  sku: string;
+  /**
+   * 仓库编码
+   */
+  warehouse: string;
+  /**
+   * 库区组
+   */
+  zoneGroup?: string;
+  [property: string]: any;
+}
+
 export interface setBindAllocateWallType {
   /**
    * 仓库

+ 2 - 2
src/views/inbound/putaway/components/LocationList.vue

@@ -11,8 +11,8 @@
       </thead>
       <tbody>
       <tr v-for="(item, index) in props.locationList" :key="index" v-if="props.locationList.length>0">
-        <td>{{ item.location }}</td>
-        <td>{{ locationType[item.type] || item.type }}</td>
+        <td>{{ item.locationId }}</td>
+        <td>{{ locationType[item.locationUsage] || item.locationUsage }}</td>
         <td>{{ item.quantity || 0 }}</td>
         <td>{{ item.max || '无' }}</td>
       </tr>

+ 88 - 12
src/views/inbound/putaway/task/index.vue

@@ -73,6 +73,18 @@
             @focus="scanType=3"
             autocomplete="off"
           >
+            <template #right-icon>
+              <van-button
+                v-if="barcodeActiveList.length > 0"
+                type="primary"
+                size="mini"
+                plain
+                :loading="changeLocationLoading"
+                @click.stop="onChangeLocation"
+              >
+                换一换
+              </van-button>
+            </template>
           </van-search>
         </div>
         <div class="barcode-input">
@@ -167,7 +179,7 @@ import { getCurrentTime } from '@/utils/date'
 import { getWaitPutawayListNew, setPutawayNew } from '@/api/putaway/index'
 import { getListCombineSku } from '@/api/picking'
 import { barcodeToUpperCase } from '@/utils/dataType.js'
-import { getRecommendedLocation } from '@/api/haikang/index'
+import { getRecommendedLocationNew } from '@/api/haikang/index'
 import { getOwnerList } from '@/hooks/basic/index'
 
 const router = useRouter()
@@ -186,7 +198,7 @@ onMounted(() => {
 })
 const warehouse = store.warehouse
 //容器号
-const containerNo = ref('')
+const containerNo = ref('zhh-p')
 //数据列表
 const dataList = ref([])
 //
@@ -373,6 +385,7 @@ const matchingBarcodeItem = (data, barcode) => {
 const switchTask = () => {
   inputBarcodeType.value = 'switchTask'
   back.value = false
+  excludedLocations.value = {}
   inputBarcodeRef.value?.show('', `请扫描容器号`, '')
 }
 
@@ -384,6 +397,10 @@ const barcodeActiveList = ref([])
 const barcodeCombineRef = ref(null)
 const putawayCombineData = ref(null)
 const combineMatchedSku = ref([])
+// 已推荐过的库位,按 lotNum 批次维度存储,用于换一换时排除
+const excludedLocations = ref({}) // { [lotNumber]: [locationId, ...] }
+// 换一换按钮 loading
+const changeLocationLoading = ref(false)
 const reset = () => {
   searchCount.value = ''
   searchBarcode.value = ''
@@ -424,13 +441,13 @@ const onDetailActive = (item) => {
   lotBarcodeTrueFalseBy.value = false
   if (putawayCombineData.value) {
     _showPutawayCombineDialog(item)
-    _getRecommendedLocation(item[0].lotNumber, item[0].owner)
+    _getRecommendedLocation(item[0])
     scanType.value = 3
     return
   }
   searchCount.value = 1
   scanType.value = 3
-  _getRecommendedLocation(item[0].lotNumber, item[0].owner)
+  _getRecommendedLocation(item[0])
   scanSuccess()
 }
 const onAsnCancel = () => {
@@ -462,7 +479,7 @@ const _handlePutawayCombineProduct = (code) => {
       if (lotBarcodeList.value.length === 1) {
         barcodeActiveList.value = lotBarcodeList.value[0]
         _showPutawayCombineDialog(lotBarcodeList.value[0])
-        _getRecommendedLocation(barcodeActiveList.value[0].lotNumber, barcodeActiveList.value[0].owner)
+        _getRecommendedLocation(barcodeActiveList.value[0])
         scanType.value = 3
       } else {
         locationList.value = []
@@ -491,7 +508,7 @@ const _handlerScan = (code) => {
       combineMatchedSku.value = []
       if (lotBarcodeList.value.length == 1) {
         barcodeActiveList.value = lotBarcodeList.value[0]
-        _getRecommendedLocation(barcodeActiveList.value[0].lotNumber, barcodeActiveList.value[0].owner)
+        _getRecommendedLocation(barcodeActiveList.value[0])
         scanType.value = 3
         scanSuccess()
       } else if (lotBarcodeList.value.length > 1) {
@@ -505,22 +522,71 @@ const _handlerScan = (code) => {
       _handlePutawayCombineProduct(code)
     }
   } else if (scanType.value == 3) {
-    searchLocation.value = barcodeToUpperCase(code)
+    const scannedLocation = barcodeToUpperCase(code)
+    // 校验是否与推荐库位一致
+    if (locationList.value.length > 0) {
+      const recommendedLocations = locationList.value.map(item => barcodeToUpperCase(item.location || ''))
+      if (!recommendedLocations.includes(scannedLocation)) {
+        showNotify({ type: 'warning', duration: 3000, message: `扫描库位${scannedLocation}与推荐库位不一致,请确认` })
+        searchLocation.value=''
+        scanError()
+        return
+      }
+    }
+    searchLocation.value = scannedLocation
     scanType.value = 4
     if (!searchCount.value) searchCount.value = 1
     scanSuccess()
   }
 }
-// 获取库存数据
-const _getRecommendedLocation = async (lotNum, owner) => {
+// 获取推荐库位
+const _getRecommendedLocation = async (item, excludeList) => {
+  const { lotNumber, owner, sku, quantity, lotAtt08 } = item
+  // 扫描商品时先看有没有推荐过
+  const listByLot = excludeList ?? (excludedLocations.value[lotNumber] || [])
+  const uniqueLocationIds = listByLot.length > 0
+    ? [...new Set(listByLot.map(loc => loc.locationId))]
+    : undefined
   try {
-    const params = { warehouse, lotNum, owner }
-    const res = await getRecommendedLocation(params)
-    locationList.value = res.data
+    const params = {
+      warehouse,
+      lotNum: lotNumber,
+      owner,
+      sku,
+      qty: quantity,
+      lotAtt08,
+      ...(uniqueLocationIds && { excludedLocations: uniqueLocationIds })
+    }
+    const res = await getRecommendedLocationNew(params)
+    if (res.data) {
+      const loc = res.data.location ?? res.data
+      // 按批次维度存储已推荐库位
+      const lotExcluded = excludedLocations.value[lotNumber] || []
+      excludedLocations.value = {
+        ...excludedLocations.value,
+        [lotNumber]: [...lotExcluded, loc]
+      }
+      locationList.value = [res.data]
+      searchCount.value = 1
+    }
   } catch (err) {
     console.error(err)
   }
 }
+
+// 换一换:请求新的推荐库位,排除当前批次已推荐过的
+const onChangeLocation = async () => {
+  if (barcodeActiveList.value.length > 0) {
+    changeLocationLoading.value = true
+    try {
+      const item = barcodeActiveList.value[0]
+      const lotExcluded = excludedLocations.value[item.lotNumber] || []
+      await _getRecommendedLocation(item, lotExcluded)
+    } finally {
+      changeLocationLoading.value = false
+    }
+  }
+}
 const numberRef = ref(null)
 const locationRef = ref(null)
 // 完成收货校验
@@ -531,6 +597,16 @@ const isCheck = () => {
     showToast({ duration: 3000, message: '请先扫描库位编号' })
     return false
   }
+  // 校验库位是否与推荐库位一致
+  if (locationList.value.length > 0) {
+    const recommendedLocations = locationList.value.map(item => barcodeToUpperCase(item.location || ''))
+    if (!recommendedLocations.includes(barcodeToUpperCase(searchLocation.value))) {
+      locationRef.value?.focus()
+      scanError()
+      showToast({ duration: 3000, message: '库位与推荐库位不一致,无法上架' })
+      return false
+    }
+  }
   if (searchCount.value == '') {
     numberRef.value?.focus()
     scanError()