Browse Source

库存并库该双击编辑优化安卓不兼容样式问题

zh 3 months ago
parent
commit
0a7aaf2875
1 changed files with 220 additions and 115 deletions
  1. 220 115
      src/views/robot/merge/index.vue

+ 220 - 115
src/views/robot/merge/index.vue

@@ -2,33 +2,47 @@
   <div class="merge-container">
     <!-- 扫描输入框区域 -->
     <div class="scan-section">
-      <van-search
-        ref="boxCodeInputRef"
-        v-model.lazy="boxCode"
-        placeholder="请扫描料箱号"
-        left-icon=""
-        :class="['scan-input', scanType === 1 ? 'scan-input-active' : '']"
-        @search="onBoxCodeEnter"
-        @focus="onBoxCodeClick"
-        autocomplete="off"
-      />
+      <div class="scan-display" @dblclick="editBoxCode">
+        <template v-if="isEditingBoxCode">
+          <van-search
+            ref="boxCodeInputRef"
+            v-model.lazy="boxCode"
+            placeholder="请扫描料箱号"
+            left-icon=""
+            class="scan-input"
+            @search="confirmBoxCode"
+            @blur="confirmBoxCode"
+            autocomplete="off"
+          />
+        </template>
+        <template v-else>
+          <span v-if="boxCode">{{ boxCode }}</span>
+          <span v-else class="placeholder">双击扫描料箱号</span>
+        </template>
+      </div>
     </div>
 
     <!-- 信息展示表格 -->
     <div class="info-table">
       <div class="table-row">
         <div class="cell label">源库位</div>
-        <div class="cell value input-cell">
-          <van-search
-            ref="sourceLocationInputRef"
-            v-model.lazy="sourceLocation"
-            placeholder="请扫描源库位"
-            left-icon=""
-            class="table-search-input"
-            @search="onSourceLocationEnter"
-            @focus="onSourceLocationClick"
-            autocomplete="off"
-          />
+        <div class="cell value input-cell" @dblclick="editSourceLocation">
+          <template v-if="isEditingSourceLocation">
+            <van-search
+              ref="sourceLocationInputRef"
+              v-model.lazy="sourceLocation"
+              placeholder="请扫描源库位"
+              left-icon=""
+              class="table-search-input"
+              @search="confirmSourceLocation"
+              @blur="confirmSourceLocation"
+              autocomplete="off"
+            />
+          </template>
+          <template v-else>
+            <span v-if="sourceLocation">{{ sourceLocation }}</span>
+            <span v-else class="placeholder">双击编辑</span>
+          </template>
         </div>
         <div class="cell label">库存数量</div>
         <div class="cell value">{{ productInfo.stockQty }}</div>
@@ -39,17 +53,23 @@
       </div>
       <div class="table-row">
         <div class="cell label">商品条码</div>
-        <div class="cell value span-2 input-cell">
-          <van-search
-            ref="barcodeInputRef"
-            v-model.lazy="scanBarcode"
-            placeholder="请扫描商品条码"
-            left-icon=""
-            class="table-search-input"
-            @search="onBarcodeEnter"
-            @focus="onBarcodeClick"
-            autocomplete="off"
-          />
+        <div class="cell value span-2 input-cell" @dblclick="editBarcode">
+          <template v-if="isEditingBarcode">
+            <van-search
+              ref="barcodeInputRef"
+              v-model.lazy="scanBarcode"
+              placeholder="请扫描商品条码"
+              left-icon=""
+              class="table-search-input"
+              @search="confirmBarcode"
+              @blur="confirmBarcode"
+              autocomplete="off"
+            />
+          </template>
+          <template v-else>
+            <span v-if="scanBarcode">{{ scanBarcode }}</span>
+            <span v-else class="placeholder">双击编辑</span>
+          </template>
         </div>
       </div>
       <div class="table-row row-small">
@@ -68,17 +88,23 @@
       </div>
       <div class="table-row">
         <div class="cell label">目标库位</div>
-        <div class="cell value input-cell input-wide">
-          <van-search
-            ref="targetLocationInputRef"
-            v-model.lazy="productInfo.targetLocationNew"
-            placeholder="请扫描目标库位"
-            left-icon=""
-            class="table-search-input"
-            @search="onTargetLocationEnter"
-            @focus="onTargetLocationClick"
-            autocomplete="off"
-          />
+        <div class="cell value input-cell input-wide" @dblclick="editTargetLocation">
+          <template v-if="isEditingTargetLocation">
+            <van-search
+              ref="targetLocationInputRef"
+              v-model.lazy="productInfo.targetLocationNew"
+              placeholder="请扫描目标库位"
+              left-icon=""
+              class="table-search-input"
+              @search="confirmTargetLocation"
+              @blur="confirmTargetLocation"
+              autocomplete="off"
+            />
+          </template>
+          <template v-else>
+            <span v-if="productInfo.targetLocationNew">{{ productInfo.targetLocationNew }}</span>
+            <span v-else class="placeholder">双击编辑</span>
+          </template>
         </div>
         <div class="cell label">移库数量</div>
         <div class="cell value editable" @dblclick="editMoveQty">
@@ -147,7 +173,7 @@
     </div>
 
     <!-- 底部按钮 -->
-    <div class="footer-buttons">
+    <div class="footer-buttons" v-show="!isAnyInputFocused">
       <van-button class="btn-robot" size="small" @click="callRobot">呼唤机器人</van-button>
       <div class="btn-right">
         <van-button type="primary" class="btn-reset" size="small" @click="resetInput">重新输入</van-button>
@@ -204,7 +230,7 @@
 
 <script setup lang="ts">
 import { closeListener, openListener, scanInit } from '@/utils/keydownListener'
-import { onMounted, onUnmounted, ref, reactive, nextTick } from 'vue'
+import { onMounted, onUnmounted, ref, reactive, nextTick, computed } from 'vue'
 import { showToast, showLoadingToast, closeToast } from 'vant'
 import { useStore } from '@/store/modules/user'
 import { getWorkingDetailsByBox, getBoxSplitCode, boxInbound, reissueTask, getBoxStatus, type BoxRelatedMergeDetailsVO, type LocationMergeDetails } from '@/api/location/merge'
@@ -249,34 +275,17 @@ onMounted(() => {
   }
   openListener()
   scanInit(_handlerScan)
-  // 获取焦点
+  // 默认进入料箱号编辑状态
   nextTick(() => {
-    focusBoxCodeInput()
+    editBoxCode()
   })
-  // 防止键盘弹出时底部按钮上移
-  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(() => {
@@ -312,40 +321,27 @@ const _handlerScan = (code: string) => {
   if (scanType.value === 1) {
     // 扫描料箱号
     boxCode.value = code
+    isEditingBoxCode.value = false
     loadBoxData(code)
   } else if (scanType.value === 2) {
     // 扫描源库位
     sourceLocation.value = code
-    onSourceLocationEnter()
+    isEditingSourceLocation.value = false
+    resetProductInfo()
+    scanType.value = 3
   } else if (scanType.value === 3) {
     // 扫描商品条码
     scanBarcode.value = code
+    isEditingBarcode.value = false
     onBarcodeEnter()
   } else if (scanType.value === 4) {
     // 扫描目标库位
     productInfo.targetLocationNew = code
-    onTargetLocationEnter()
-  }
-}
-
-// 料箱号输入框点击 - 重置所有数据
-const onBoxCodeClick = () => {
-  scanType.value = 1
-}
-
-// 料箱号回车
-const onBoxCodeEnter = () => {
-  scanType.value = 1
-  if (boxCode.value && boxCode.value.length > 5) {
-    loadBoxData(boxCode.value)
+    isEditingTargetLocation.value = false
+    showToast(`已输入目标库位: ${code}`)
   }
 }
 
-// 源库位输入框点击 - 重置除料箱号外的数据
-const onSourceLocationClick = () => {
-  scanType.value = 2
-}
-
 // 源库位回车
 const onSourceLocationEnter = () => {
   if (!sourceLocation.value) return
@@ -355,17 +351,6 @@ const onSourceLocationEnter = () => {
   
   // 切换到扫描商品条码
   scanType.value = 3
-  focusBarcodeInput()
-}
-
-// 商品条码输入框点击 - 只重置商品信息
-const onBarcodeClick = () => {
-  scanType.value = 3
-}
-
-// 目标库位输入框点击
-const onTargetLocationClick = () => {
-  scanType.value = 4
 }
 
 // 目标库位回车
@@ -417,8 +402,11 @@ const onBarcodeEnter = async () => {
       scanSuccess()
       showToast('商品信息获取成功')
       // 切换到扫描目标库位
+      isEditingBarcode.value = false
       scanType.value = 4
-      focusTargetLocationInput()
+      nextTick(() => {
+        editTargetLocation()
+      })
     } else {
       scanError()
       showToast('未找到库存信息')
@@ -442,8 +430,17 @@ const resetAllData = () => {
   clickableLocationsMap.value = new Map()
   resetProductInfo()
   initStations()
+  // 关闭所有编辑状态
+  isEditingBoxCode.value = false
+  isEditingSourceLocation.value = false
+  isEditingBarcode.value = false
+  isEditingTargetLocation.value = false
+  isEditingMoveQty.value = false
   scanType.value = 1
-  focusBoxCodeInput()
+  // 进入料箱号编辑
+  nextTick(() => {
+    editBoxCode()
+  })
 }
 
 // 重置除料箱号外的数据
@@ -452,8 +449,16 @@ const resetExceptBoxCode = () => {
   scanBarcode.value = ''
   selectedBox.value = null
   resetProductInfo()
+  // 关闭编辑状态
+  isEditingSourceLocation.value = false
+  isEditingBarcode.value = false
+  isEditingTargetLocation.value = false
+  isEditingMoveQty.value = false
   scanType.value = 2
-  focusSourceLocationInput()
+  // 进入源库位编辑
+  nextTick(() => {
+    editSourceLocation()
+  })
 }
 
 // 重置商品信息
@@ -524,9 +529,12 @@ const loadBoxData = async (code: string) => {
       startPolling()
     }
     
-    // 加载完成后focus到源库位输入框
+    // 加载完成后进入源库位编辑状态
+    isEditingBoxCode.value = false
     scanType.value = 2
-    focusSourceLocationInput()
+    nextTick(() => {
+      editSourceLocation()
+    })
   } catch (error: any) {
     closeToast()
     scanError()
@@ -618,6 +626,77 @@ const confirmMoveQty = () => {
   isEditingMoveQty.value = false
 }
 
+// 料箱号编辑
+const isEditingBoxCode = ref(false)
+const editBoxCode = () => {
+  isEditingBoxCode.value = true
+  scanType.value = 1
+  nextTick(() => {
+    boxCodeInputRef.value?.focus()
+  })
+}
+const confirmBoxCode = () => {
+  isEditingBoxCode.value = false
+  if (boxCode.value && boxCode.value.length > 5) {
+    loadBoxData(boxCode.value)
+  }
+}
+
+// 源库位编辑
+const isEditingSourceLocation = ref(false)
+const editSourceLocation = () => {
+  isEditingSourceLocation.value = true
+  scanType.value = 2
+  nextTick(() => {
+    sourceLocationInputRef.value?.focus()
+  })
+}
+const confirmSourceLocation = () => {
+  isEditingSourceLocation.value = false
+  if (sourceLocation.value) {
+    resetProductInfo()
+    scanType.value = 3
+  }
+}
+
+// 商品条码编辑
+const isEditingBarcode = ref(false)
+const editBarcode = () => {
+  isEditingBarcode.value = true
+  scanType.value = 3
+  nextTick(() => {
+    barcodeInputRef.value?.focus()
+  })
+}
+const confirmBarcode = () => {
+  isEditingBarcode.value = false
+  if (scanBarcode.value) {
+    onBarcodeEnter()
+  }
+}
+
+// 目标库位编辑
+const isEditingTargetLocation = ref(false)
+const editTargetLocation = () => {
+  isEditingTargetLocation.value = true
+  scanType.value = 4
+  nextTick(() => {
+    targetLocationInputRef.value?.focus()
+  })
+}
+const confirmTargetLocation = () => {
+  isEditingTargetLocation.value = false
+  if (productInfo.targetLocationNew) {
+    showToast(`已输入目标库位: ${productInfo.targetLocationNew}`)
+  }
+}
+
+// 是否有任何输入框处于编辑状态(用于隐藏底部按钮)
+const isAnyInputFocused = computed(() => {
+  return isEditingBoxCode.value || isEditingSourceLocation.value || 
+         isEditingBarcode.value || isEditingTargetLocation.value || isEditingMoveQty.value
+})
+
 // 站台数据结构
 interface SubLocation {
   id: string
@@ -977,7 +1056,9 @@ const confirmSelectLocation = () => {
     showToast(`已选择源库位: ${currentLocation.id}`)
     // 切换到扫描商品条码
     scanType.value = 3
-    focusBarcodeInput()
+    nextTick(() => {
+      editBarcode()
+    })
   } else {
     // 推荐保留库位,填入目标库位
     productInfo.targetLocationNew = currentLocation.id
@@ -1087,25 +1168,41 @@ const submitMove = () => {
 .scan-section {
   margin-bottom: 12px;
 
+  .scan-display {
+    background: #fff;
+    border-radius: 4px;
+    padding: 10px 12px;
+    min-height: 24px;
+    display: flex;
+    align-items: center;
+    cursor: pointer;
+
+    .placeholder {
+      color: #999;
+      font-size: 14px;
+    }
+
+    span:not(.placeholder) {
+      font-size: 14px;
+      font-weight: 500;
+      color: #333;
+    }
+  }
+
   .scan-input {
     padding: 0;
     background: #fff;
     border-radius: 4px;
+    width: 100%;
 
     :deep(.van-search__content) {
       background: #fff;
-      padding-left: 12px;
+      padding-left: 0;
     }
 
     :deep(.van-field__control) {
       font-size: 14px;
     }
-
-    &.scan-input-active {
-      :deep(.van-search__content) {
-        border-bottom: 2px solid #1989fa;
-      }
-    }
   }
 }
 
@@ -1154,15 +1251,22 @@ const submitMove = () => {
       color: #333;
     
       &.input-cell {
-        padding: 0;
+        padding: 0 6px;
+        cursor: pointer;
+
+        .placeholder {
+          color: #999;
+          font-size: 12px;
+        }
 
         .table-search-input {
           padding: 0;
           background: transparent;
+          width: 100%;
 
           :deep(.van-search__content) {
             background: transparent;
-            padding-left: 6px;
+            padding-left: 0;
           }
 
           :deep(.van-field__control) {
@@ -1348,19 +1452,20 @@ const submitMove = () => {
   background: #fff;
   box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
   z-index: 100;
-  /* 防止键盘弹出时上移 */
-  transform: translateZ(0);
 
   .btn-right {
     display: flex;
-    gap: 12px; /* 增加按钮间距 */
+    /* 使用 margin 替代 gap,兼容安卓 WebView */
+    .van-button + .van-button {
+      margin-left: 12px;
+    }
   }
 
   .van-button {
     height: 32px;
     font-size: 13px;
-    padding: 0 12px;
-    min-width: 70px; /* 确保按钮最小宽度 */
+    padding: 0 14px;
+    min-width: 75px;
   }
 
   .btn-robot {