zh 3 сар өмнө
parent
commit
a13e73e420

+ 132 - 64
src/views/robot/merge/index.vue

@@ -2,13 +2,15 @@
   <div class="merge-container">
     <!-- 扫描输入框区域 -->
     <div class="scan-section">
-      <van-field
+      <van-search
         ref="boxCodeInputRef"
-        v-model="boxCode"
+        v-model.lazy="boxCode"
         placeholder="请扫描料箱号"
-        clearable
-        @click="onBoxCodeClick"
-        @keyup.enter="onBoxCodeEnter"
+        left-icon=""
+        :class="['scan-input', scanType === 1 ? 'scan-input-active' : '']"
+        @search="onBoxCodeEnter"
+        @focus="onBoxCodeClick"
+        autocomplete="off"
       />
     </div>
 
@@ -17,13 +19,15 @@
       <div class="table-row">
         <div class="cell label">源库位</div>
         <div class="cell value input-cell">
-          <van-field
+          <van-search
             ref="sourceLocationInputRef"
-            v-model="sourceLocation"
+            v-model.lazy="sourceLocation"
             placeholder="请扫描源库位"
-            clearable
-            @click="onSourceLocationClick"
-            @keyup.enter="onSourceLocationEnter"
+            left-icon=""
+            class="table-search-input"
+            @search="onSourceLocationEnter"
+            @focus="onSourceLocationClick"
+            autocomplete="off"
           />
         </div>
         <div class="cell label">库存数量</div>
@@ -36,13 +40,15 @@
       <div class="table-row">
         <div class="cell label">商品条码</div>
         <div class="cell value span-2 input-cell">
-          <van-field
+          <van-search
             ref="barcodeInputRef"
-            v-model="scanBarcode"
+            v-model.lazy="scanBarcode"
             placeholder="请扫描商品条码"
-            clearable
-            @click="onBarcodeClick"
-            @keyup.enter="onBarcodeEnter"
+            left-icon=""
+            class="table-search-input"
+            @search="onBarcodeEnter"
+            @focus="onBarcodeClick"
+            autocomplete="off"
           />
         </div>
       </div>
@@ -63,13 +69,15 @@
       <div class="table-row">
         <div class="cell label">目标库位</div>
         <div class="cell value input-cell input-wide">
-          <van-field
+          <van-search
             ref="targetLocationInputRef"
-            v-model="productInfo.targetLocationNew"
+            v-model.lazy="productInfo.targetLocationNew"
             placeholder="请扫描目标库位"
-            clearable
-            @click="onTargetLocationClick"
-            @keyup.enter="onTargetLocationEnter"
+            left-icon=""
+            class="table-search-input"
+            @search="onTargetLocationEnter"
+            @focus="onTargetLocationClick"
+            autocomplete="off"
           />
         </div>
         <div class="cell label">移库数量</div>
@@ -245,13 +253,30 @@ onMounted(() => {
   nextTick(() => {
     focusBoxCodeInput()
   })
+  // 防止键盘弹出时底部按钮上移
+  if (window.visualViewport) {
+    window.visualViewport.addEventListener('resize', handleViewportResize)
+  }
 })
 
 onUnmounted(() => {
   closeListener()
   stopPolling()
+  // 移除viewport监听
+  if (window.visualViewport) {
+    window.visualViewport.removeEventListener('resize', handleViewportResize)
+  }
 })
 
+// 处理viewport变化(键盘弹出/收起)
+const handleViewportResize = () => {
+  // 保持页面滚动位置,防止键盘弹出时页面跳动
+  const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
+  requestAnimationFrame(() => {
+    window.scrollTo(0, scrollTop)
+  })
+}
+
 // 设置料箱号输入框焦点
 const focusBoxCodeInput = () => {
   nextTick(() => {
@@ -283,7 +308,7 @@ const focusTargetLocationInput = () => {
 // 扫描监听
 const _handlerScan = (code: string) => {
   if (!code) return
-  
+
   if (scanType.value === 1) {
     // 扫描料箱号
     boxCode.value = code
@@ -305,11 +330,12 @@ const _handlerScan = (code: string) => {
 
 // 料箱号输入框点击 - 重置所有数据
 const onBoxCodeClick = () => {
-  resetAllData()
+  scanType.value = 1
 }
 
 // 料箱号回车
 const onBoxCodeEnter = () => {
+  scanType.value = 1
   if (boxCode.value && boxCode.value.length > 5) {
     loadBoxData(boxCode.value)
   }
@@ -317,16 +343,16 @@ const onBoxCodeEnter = () => {
 
 // 源库位输入框点击 - 重置除料箱号外的数据
 const onSourceLocationClick = () => {
-  resetExceptBoxCode()
+  scanType.value = 2
 }
 
 // 源库位回车
 const onSourceLocationEnter = () => {
   if (!sourceLocation.value) return
-  
+
   // 清空商品信息
   resetProductInfo()
-  
+
   // 切换到扫描商品条码
   scanType.value = 3
   focusBarcodeInput()
@@ -334,7 +360,7 @@ const onSourceLocationEnter = () => {
 
 // 商品条码输入框点击 - 只重置商品信息
 const onBarcodeClick = () => {
-  resetProductInfo()
+  scanType.value = 3
 }
 
 // 目标库位输入框点击
@@ -358,36 +384,36 @@ const onBarcodeEnter = async () => {
     showToast('请先扫描源库位')
     return
   }
-  
+
   try {
     showLoadingToast({ message: '查询中...', forbidClick: true })
-    
+
     const params = {
       warehouse,
       barcode: scanBarcode.value,
       location: sourceLocation.value,
       locationRegexp: '^(?!STAGE_|SORTATION_).*$'
     }
-    
+
     const res = await getInventory(params)
     closeToast()
-    
+
     if (res.data && res.data.length > 0) {
       const inventoryData = res.data[0]
       // 保存完整的库存数据
       currentInventoryData.value = inventoryData
       // 填充商品信息
       productInfo.targetLocation = sourceLocation.value
-      productInfo.stockQty = inventoryData.quantityAvailable || inventoryData.quantity || ''
-      productInfo.productName = inventoryData.productName || inventoryData.skuName || ''
-      productInfo.barcode = inventoryData.barcode || scanBarcode.value
-      productInfo.qualityStatus = inventoryData.lotAtt08 || inventoryData.qualityStatus || ''
-      productInfo.warehouseType = inventoryData.lotAtt05 || inventoryData.warehouseType || ''
-      productInfo.batchNo = inventoryData.lotNumber || inventoryData.lotNum || ''
-      productInfo.productionDate = inventoryData.lotAtt01 || inventoryData.productionDate || ''
-      productInfo.expiryDate = inventoryData.lotAtt02 || inventoryData.expiryDate || ''
-      productInfo.moveQty = inventoryData.quantityAvailable || inventoryData.quantity || ''
-      
+      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
+      productInfo.moveQty = inventoryData.quantityAvailable + inventoryData.quantityAvailable
+
       scanSuccess()
       showToast('商品信息获取成功')
       // 切换到扫描目标库位
@@ -492,12 +518,12 @@ const loadBoxData = async (code: string) => {
 
     closeToast()
     scanSuccess()
-    
+
     // 加载完成后检查是否需要启动轮询
     if (hasWaitingBox()) {
       startPolling()
     }
-    
+
     // 加载完成后focus到源库位输入框
     scanType.value = 2
     focusSourceLocationInput()
@@ -808,19 +834,19 @@ const refreshBoxStatus = async () => {
   try {
     const res = await getBoxStatus(warehouse, boxCodeList)
     const statusMap = res.data || {}
-    
+
     // 更新站台列表中的状态
     stationList.value = stationList.value.map(station => {
       if (!station.boxCode || !statusMap.hasOwnProperty(station.boxCode)) {
         return station
       }
-      
+
       const newBoxStatus = statusMap[station.boxCode]
       const inventoryLocations = station.inventoryLocations || []
-      
+
       let status: StationItem['status'] = 'offline'
       let label: string | undefined = undefined
-      
+
       if (newBoxStatus === 0 || newBoxStatus === 10) {
         status = 'waiting'
         label = '等待调箱'
@@ -837,10 +863,10 @@ const refreshBoxStatus = async () => {
         status = 'error'
         label = '异'
       }
-      
+
       return { ...station, status, label }
     })
-    
+
     // 检查是否需要继续轮询
     if (hasWaitingBox()) {
       startPolling()
@@ -944,9 +970,20 @@ const selectSubLocation = (station: StationItem, sub: SubLocation) => {
 
 // 确认选择库位
 const confirmSelectLocation = () => {
-  productInfo.targetLocationNew = currentLocation.id
-  showLocationPopup.value = false
-  showToast(`已选择库位: ${currentLocation.id}`)
+  if (currentLocation.recommendType === 'clear') {
+    // 推荐清空库位,填入源库位
+    sourceLocation.value = currentLocation.id
+    showLocationPopup.value = false
+    showToast(`已选择源库位: ${currentLocation.id}`)
+    // 切换到扫描商品条码
+    scanType.value = 3
+    focusBarcodeInput()
+  } else {
+    // 推荐保留库位,填入目标库位
+    productInfo.targetLocationNew = currentLocation.id
+    showLocationPopup.value = false
+    showToast(`已选择目标库位: ${currentLocation.id}`)
+  }
 }
 
 // 呼唤机器人
@@ -957,6 +994,8 @@ const callRobot = async () => {
     closeToast()
     scanSuccess()
     showToast('呼唤机器人成功')
+    // 重置页面数据并聚焦到料箱输入框
+    resetAllData()
   } catch (error: any) {
     closeToast()
     scanError()
@@ -1050,8 +1089,25 @@ const submitMove = () => {
 .scan-section {
   margin-bottom: 12px;
 
-  :deep(.van-field) {
+  .scan-input {
+    padding: 0;
+    background: #fff;
     border-radius: 4px;
+
+    :deep(.van-search__content) {
+      background: #fff;
+      padding-left: 12px;
+    }
+
+    :deep(.van-field__control) {
+      font-size: 14px;
+    }
+
+    &.scan-input-active {
+      :deep(.van-search__content) {
+        border-bottom: 2px solid #1989fa;
+      }
+    }
   }
 }
 
@@ -1098,23 +1154,25 @@ const submitMove = () => {
 
     &.value {
       color: #333;
-    
+
       &.input-cell {
         padding: 0;
-    
-        :deep(.van-field) {
-          padding: 4px 6px;
-    
-          .van-field__body {
-            height: 24px;
+
+        .table-search-input {
+          padding: 0;
+          background: transparent;
+
+          :deep(.van-search__content) {
+            background: transparent;
+            padding-left: 6px;
           }
-    
-          .van-field__control {
+
+          :deep(.van-field__control) {
             font-size: 13px;
           }
         }
       }
-    
+
       &.editable {
         cursor: pointer;
         min-height: 20px;
@@ -1288,18 +1346,28 @@ const submitMove = () => {
   justify-content: space-between;
   align-items: center;
   padding: 10px 12px;
+  padding-bottom: calc(10px + env(safe-area-inset-bottom));
   background: #fff;
   box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
+  z-index: 100;
+  /* 防止键盘弹出时上移 */
+  transform: translate3d(0, 0, 0);
+  backface-visibility: hidden;
+  -webkit-backface-visibility: hidden;
 
   .btn-right {
     display: flex;
-    gap: 8px;
+    /* 使用 margin 替代 gap,兼容安卓 WebView */
+    .van-button + .van-button {
+      margin-left: 12px;
+    }
   }
 
   .van-button {
     height: 32px;
     font-size: 13px;
-    padding: 0 12px;
+    padding: 0 14px;
+    min-width: 75px;
   }
 
   .btn-robot {