zhaohuanhuan 7 месяцев назад
Родитель
Сommit
f911d34a23
1 измененных файлов с 123 добавлено и 19 удалено
  1. 123 19
      src/views/inventory/transfer/index.vue

+ 123 - 19
src/views/inventory/transfer/index.vue

@@ -125,16 +125,17 @@
                   v-for="(product, index) in productList"
                   :key="product.id"
                   :class="{ selected: isSelected(product) }"
+                  :style="getRowStyle(product)"
                   @click="onProductSelect(product)"
                   class="clickable-row"
               >
-                <td
-                  v-if="isFirstInOwnerGroup(product, index)"
+                <td 
+                  v-if="shouldShowOwner(product, index)"
                   :rowspan="getOwnerRowspan(product, index)"
-                  class="owner-cell"
+                  class="owner-cell" 
                   style="width: 40px"
                 >
-                  {{ product.owner }}
+                  {{ shouldShowOwnerText(product, index) ? product.owner : '' }}
                 </td>
                 <td class="location-cell">{{ product.location }}</td>
                 <td class="barcode-cell">{{ product.barcode }}</td>
@@ -144,6 +145,7 @@
                 <td class="checkbox-cell">
                   <van-checkbox
                     :model-value="isSelected(product)"
+                    :disabled="product.quantityAvailable <= 0"
                     @update:model-value="onProductSelect(product)"
                   />
                 </td>
@@ -162,8 +164,8 @@
   </div>
 </template>
 <script setup lang="ts">
-import { ref, onMounted, onUnmounted, computed, nextTick } from 'vue'
-import { showConfirmDialog, showNotify, showToast } from 'vant'
+import { ref, onMounted, onUnmounted, nextTick } from 'vue'
+import { showConfirmDialog, showNotify } from 'vant'
 import nodataUrl from '@/assets/nodata.png'
 import { useRouter } from 'vue-router'
 import { useStore } from '@/store/modules/user'
@@ -254,7 +256,14 @@ const _handlerScan = (code) => {
           return b.location.localeCompare(a.location)
         })
         productList.value = res.data
-        onProductSelect(productList.value[0])
+        // 查找第一个可用数量大于0的商品进行选中
+        const firstAvailableProduct = productList.value.find(item => item.quantityAvailable > 0)
+        if (firstAvailableProduct) {
+          onProductSelect(firstAvailableProduct)
+        } else {
+          // 如果所有商品可用数量都为0,则不选择任何商品
+          selectedProducts.value = {}
+        }
         // 数据加载完成后重新计算表格高度
         setTimeout(() => {
           calculateTableHeight()
@@ -289,7 +298,7 @@ const _handlerScan = (code) => {
   }else if (scanType.value == 4) {
     scanSuccess()
     targetLocation.value = code
-    tips.value = '请手动进行移库操作'
+    onConfirm()
   }
   targetLocationRef.value?.blur()
   productBarcodeRef.value?.blur()
@@ -333,13 +342,13 @@ const onConfirm=()=>{
   showConfirmDialog({
     title: '移库确认',
     message:
-      `${productBarcode.value}从"${sourceLocation.value}"移动至"${targetLocation.value}"-${transferQuantity.value}件`
+      `${productBarcode.value}从"${sourceLocation.value}"移动至"${targetLocation.value}"共:${transferQuantity.value}件`
   })
     .then(() => {
-      const {fmContainer,lotNumber,ownerCode,sku,location}=selectedProducts.value
+      const {traceId,lotNumber,ownerCode,sku}=selectedProducts.value
       const data={
         fmLocation:sourceLocation.value,
-        fmContainer,
+        fmContainer:traceId,
         owner:ownerCode,
         sku,
         lotNum:lotNumber,
@@ -348,7 +357,7 @@ const onConfirm=()=>{
         toLocation:targetLocation.value
       }
       showLoading()
-      inventoryMovement(data).then(res=>{
+      inventoryMovement(data).then(()=>{
         closeLoading()
         scanSuccess()
         showNotify({ type: 'success', duration: 3000, message: `操作成功,请继续扫描商品条码` })
@@ -398,6 +407,11 @@ const calculateTableHeight = () => {
 }
 
 const onProductSelect = (product) => {
+  // 如果可用数量为0,则不允许选择
+  if (product.quantityAvailable <= 0) {
+    return
+  }
+
   selectedProducts.value = product
   // 选择商品时自动赋值移库数量
   transferQuantity.value = product.quantityAvailable
@@ -411,6 +425,67 @@ const isSelected = (product) => {
   return selectedProducts.value?.id === product.id
 }
 
+// 根据 locationUsage 返回行样式
+const getRowStyle = (product) => {
+  const locationUsageColors = {
+    'PC': 'white',
+    'CS': 'white',
+    'EA': 'white',
+    'RS': 'rgb(255, 250, 250)', // Snow
+    'ST': 'lightgray'
+  }
+
+  const backgroundColor = locationUsageColors[product.locationUsage] || 'white'
+
+  return {
+    backgroundColor
+  }
+}
+
+// 判断是否应该显示货主单元格(始终显示单元格)
+const shouldShowOwner = (product, index: number) => {
+  // 如果当前行被选中,则显示单元格
+  if (isSelected(product)) {
+    return true
+  }
+  
+  // 检查同一货主组中是否有选中的行
+  const sameOwnerProducts = productList.value.filter(p => p.owner === product.owner)
+  const hasSelectedInGroup = sameOwnerProducts.some(p => isSelected(p))
+  
+  // 如果同一货主组中有选中的行,则其他未选中行显示空单元格
+  if (hasSelectedInGroup) {
+    // 检查当前行是否为未选中的连续组的第一行
+    if (index === 0 || productList.value[index - 1].owner !== product.owner || isSelected(productList.value[index - 1])) {
+      return true
+    }
+    return false
+  }
+  
+  // 如果同一货主组中没有选中的行,则在第一行显示单元格
+  return isFirstInOwnerGroup(product, index)
+}
+
+// 判断是否应该显示货主文字
+const shouldShowOwnerText = (product, index: number) => {
+  // 如果当前行被选中,则显示文字
+  if (isSelected(product)) {
+    return true
+  }
+  
+  // 检查同一货主组中是否有选中的行
+  const sameOwnerProducts = productList.value.filter(p => p.owner === product.owner)
+  const hasSelectedInGroup = sameOwnerProducts.some(p => isSelected(p))
+  
+  // 如果同一货主组中有选中的行,则其他未选中行不显示文字
+  if (hasSelectedInGroup) {
+    return false
+  }
+  
+  // 如果同一货主组中没有选中的行,则在第一行显示文字
+  return isFirstInOwnerGroup(product, index)
+}
+
 // 检查是否为同一货主的第一行
 const isFirstInOwnerGroup = (product, index: number) => {
   if (index === 0) return true
@@ -419,6 +494,30 @@ const isFirstInOwnerGroup = (product, index: number) => {
 
 // 计算相同货主的行跨度
 const getOwnerRowspan = (product, index: number) => {
+  // 如果当前行被选中,rowspan为1
+  if (isSelected(product)) {
+    return 1
+  }
+  
+  // 检查同一货主组中是否有选中的行
+  const sameOwnerProducts = productList.value.filter(p => p.owner === product.owner)
+  const hasSelectedInGroup = sameOwnerProducts.some(p => isSelected(p))
+  
+  // 如果同一货主组中有选中的行,则计算未选中行的rowspan
+  if (hasSelectedInGroup) {
+    let rowspan = 1
+    // 向下查找连续的未选中的同货主行
+    for (let i = index + 1; i < productList.value.length; i++) {
+      if (productList.value[i].owner === product.owner && !isSelected(productList.value[i])) {
+        rowspan++
+      } else {
+        break
+      }
+    }
+    return rowspan
+  }
+  
+  // 计算正常的rowspan(没有选中行的情况)
   let rowspan = 1
   for (let i = index + 1; i < productList.value.length; i++) {
     if (productList.value[i].owner === product.owner) {
@@ -429,6 +528,7 @@ const getOwnerRowspan = (product, index: number) => {
   }
   return rowspan
 }
+
 // 数据刷新
 const loadData = () => {
 }
@@ -440,7 +540,7 @@ onUnmounted(() => {
   }
   window.removeEventListener('resize', calculateTableHeight)
 })
-window.onRefresh = loadData
+// window.onRefresh = loadData
 </script>
 
 <style scoped>
@@ -679,7 +779,7 @@ window.onRefresh = loadData
 
 .header-table th:nth-child(2),
 .body-table td:nth-child(2) {
-  width: 15%;
+  width: 25%;
 }
 
 .header-table th:nth-child(3),
@@ -715,11 +815,9 @@ window.onRefresh = loadData
   border-collapse: collapse;
 }
 
-.product-table th{
-  padding: 8px 0;
-}
+.product-table th,
 .product-table td {
-  padding:0;
+  padding: 8px 0;
   text-align: center;
   border-bottom: 1px solid #ebedf0;
   font-size: 12px;
@@ -749,6 +847,12 @@ window.onRefresh = loadData
 .checkbox-cell {
   width: 25px;
 }
-
+::v-deep(.checkbox-cell .van-checkbox){
+  justify-content: center;
+}
+::v-deep(.checkbox-cell .van-checkbox__icon){
+  background: #fff;
+  border-radius: 50%;
+}
 
 </style>