Browse Source

fix: 修复路由跳转路径和优化物料管理逻辑

修复多个页面中路由跳转路径从'/home'改为'/'的问题
优化物料管理页面逻辑,包括:
1. 增加物料选择功能
2. 改进物料查询状态处理
3. 添加未识别物料统计
4. 优化入库确认流程
5. 调整页面文本和按钮描述
yangzhijie 5 months ago
parent
commit
3a423e7e69

+ 5 - 5
src/login/UserHome.vue

@@ -132,7 +132,7 @@
         <div class="modal-content-row">
           <div class="modal-text">
             <h3>请确认您要进行的操作</h3>
-            <p>您是否已经申请了领料?</p>
+            <p>您是否需要先领料(如果已经有领料单可以直接拣货),如果是的话请先点击【先领料】按钮,否则直接点击【直接拣货】按钮。</p>
           </div>
           <div class="modal-icon">
             <div class="icon-box">
@@ -141,8 +141,8 @@
           </div>
         </div>
         <div class="modal-footer">
-          <button class="modal-btn cancel-btn" @click="handlePickingNo"></button>
-          <button class="modal-btn confirm-btn" @click="handlePickingYes"></button>
+          <button class="modal-btn cancel-btn" @click="handlePickingNo">先领料</button>
+          <button class="modal-btn confirm-btn" @click="handlePickingYes">直接拣货</button>
         </div>
       </div>
     </div>
@@ -492,8 +492,8 @@ const goToAbnormalArea = () => {
 
 // 外侧屏幕操作按钮
 const outButtons = reactive([
-    { label: '领料', action: 'materialOut' },
-    { label: '拣货', action: 'materialReturn' },
+    // { label: '领料', action: 'materialOut' },
+    { label: '领料', action: 'materialReturn' },
     { label: '入库', action: 'materialIn' },
     // { label: 'AGV RFID\n校验', action: 'agvRfidRecognition' },
     { label: '成品\n入库', action: 'finishedProductIn' },

+ 168 - 63
src/stock-in/InConfirm.vue

@@ -10,10 +10,10 @@
         <i class="fas fa-home" />
         <span>主页</span>
       </button>
-      <h1 class="page-title">还料入库</h1>
+      <h1 class="page-title">入库</h1>
       <!-- 右侧操作按钮 -->
       <div class="header-actions">
-        <button class="action-btn refresh-btn" @click="verify">
+        <button class="action-btn refresh-btn" @click="resetView">
           <i class="fas fa-sync-alt" />
           <span>重新校验</span>
         </button>
@@ -24,9 +24,8 @@
     <main class="main-content">
       <!-- 统计信息 -->
       <div v-if="materialList.length > 0" class="stats-section">
-        <span class="stats-text">共 {{ materialList.length }} 条数据</span>
+        <span class="stats-text">共 {{ materialList.length }} 条数据,不识别 {{ unrecognizedCount }} 条</span>
       </div>
-
       <!-- 卡片网格区域 -->
       <div class="card-grid-wrapper">
         <!-- 空状态 -->
@@ -37,54 +36,61 @@
 
         <!-- 卡片网格 -->
         <div v-else class="card-grid">
-          <div
-            v-for="(item, index) in materialList"
-            :key="item.id || index"
-            class="inventory-card"
-            :class="getCardClass(item.remarks)"
-          >
-            <!-- 卡片序号 -->
-            <div class="card-index" :class="getCardClass(item.remarks)">{{ index + 1 }}</div>
-
-            <!-- 图片区域 -->
-            <div class="card-image">
-              <div class="image-placeholder" :class="getCardClass(item.remarks)">
-                <i :class="getInventoryIcon(item.inventoryType)" />
+          <template v-for="(item, index) in materialList" :key="item.id || index">
+            <div
+              v-if="item.inventoryId != null"              
+              class="inventory-card"
+              :class="getCardClass(item.remarks)"
+              @click="handleSelect(item)"
+            >
+              <!-- 卡片序号 -->
+              <div
+                v-if="item.selected" class="card-index" 
+                style="background: linear-gradient(135deg, #a8f63b 0%, #60faee 100%);" 
+                :class="getCardClass(item.remarks)"
+              />
+
+              <!-- 图片区域 -->
+              <div class="card-image">
+                <div class="image-placeholder" :class="getCardClass(item.remarks)">
+                  <i :class="getInventoryIcon(item.inventoryType)" />
+                </div>
               </div>
-            </div>
 
-            <!-- 信息区域 -->
-            <div class="card-info">
-              <div class="info-row">
-                <span class="info-label">名称:</span>
-                <span class="info-value">{{ item.inventoryName || '-' }}</span>
-              </div>
-              <div class="info-row">
-                <span class="info-label">编号:</span>
-                <span class="info-value">{{ item.inventoryNo || '-' }}</span>
+              <!-- 信息区域 -->
+              <div class="card-info">
+                <div class="info-row">
+                  <span class="info-label">名称:</span>
+                  <span class="info-value">{{ item.inventoryName || '-' }}</span>
+                </div>
+                <div class="info-row">
+                  <span class="info-label">编号:</span>
+                  <span class="info-value">{{ item.inventoryNo || '-' }}</span>
+                </div>
+                <div class="info-row location-row">
+                  <i class="fas fa-map-marker-alt location-icon" />
+                  <span class="info-value">{{ item.positionName || '-' }} / {{ item.warehouseName || '-' }}</span>
+                </div>
               </div>
-              <div class="info-row location-row">
-                <i class="fas fa-map-marker-alt location-icon" />
-                <span class="info-value">{{ item.positionName || '-' }} / {{ item.warehouseName || '-' }}</span>
-              </div>
-            </div>
 
-            <!-- 状态区域(固定高度) -->
-            <div class="card-status-section">
-              <div class="status-badge" :class="getCardClass(item.remarks)">
-                <i class="fas fa-exclamation-circle" />
-                {{ item.remarks || '-' }}
+              <!-- 状态区域(固定高度) -->
+              <div class="card-status-section">
+                <div class="status-badge" :class="getCardClass(item.remarks)">
+                  <i class="fas fa-exclamation-circle" />
+                  {{ item.remarks || '-' }}
+                </div>
               </div>
             </div>
-          </div>
+          </template>
         </div>
       </div>
     </main>
 
     <!-- 底部操作按钮 -->
     <div class="bottom-actions">
-      <button class="submit-btn" :disabled="notInStockCount === 0" @click="handleComplete">
-        还料入库
+      <button class="submit-btn" @click="handleComplete">
+        确认入库 
+        <span v-if="validStockCount != 0">{{ validStockCount }}</span>
       </button>
     </div>
 
@@ -98,6 +104,29 @@
       <span class="loading-text">加载中...</span>
     </div>
   </div>
+
+
+
+  <!-- 直接进入仓库提示 -->
+  <div v-if="enterConfirmVisible" class="tech-modal-overlay" @click.self="enterConfirmVisible = false">
+    <div class="tech-modal">
+      <div class="modal-content-row">
+        <div class="modal-text">
+          <h3>请确认您要直接进入仓库</h3>
+          <p>系统检测到您未携带物料,或者未勾选任何物料,是否确认直接进入仓库?</p>
+        </div>
+        <div class="modal-icon">
+          <div class="icon-box">
+            <i class="fas fa-clipboard-check" />
+          </div>
+        </div>
+      </div>
+      <div class="modal-footer">
+        <button class="modal-btn cancel-btn" @click="enterConfirm">直接进入仓库</button>
+        <button class="modal-btn confirm-btn" @click="enterConfirmVisible = false">取消</button>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script setup>
@@ -124,8 +153,6 @@ const loading = ref(false);
 // 物料列表数据
 const materialList = ref([]);
 const epcs = ref([]);
-// 临时收集epc数据的数组
-const tempEpcs = ref([]);
 
 // 分页配置
 const pagination = reactive({
@@ -135,8 +162,8 @@ const pagination = reactive({
 });
 
 // 计算不在库的数量
-const notInStockCount = computed(() => {
-    return materialList.value.filter(item => item.remarks === '不在库').length;
+const validStockCount = computed(() => {
+    return materialList.value.filter(item => item.remarks === '不在库' && item.selected === true).length;
 });
 
 // 根据 remarks 返回卡片样式类
@@ -172,16 +199,16 @@ const getInventoryIcon = type => {
 // 还料入库
 const handleComplete = async () => {
     // 只处理不在库的数据
-    const notInStockItems = materialList.value.filter(item => item.remarks === '不在库');
+    const notInStockItems = materialList.value.filter(item => item.selected === true);
 
     if (notInStockItems.length === 0) {
-        showNotify({ type: 'danger', message: '没有需要入库的物料!' });
+        enterConfirmVisible.value = true;
         return;
     }
 
     const params = [];
-    notInStockItems.forEach(item => {
-        if (item.remarks === '不在库') {
+    materialList.value.forEach(item => {
+        if (item.selected === true) {
             params.push({
                 inventoryId: item.inventoryId,
             });
@@ -193,24 +220,53 @@ const handleComplete = async () => {
 };
 
 // 校验
-const verify = () => {
-    getList();
+const resetView = () => {
+    epcs.value = [];
+    materialList.value = [];
 };
 
 // 获取物料列表(外侧校验)
 const getList = async () => {
     // loading.value = true;
-    try {
 
-        const params = {
-            epcList: epcs.value,
-        };
+    const params = {
+        epcList: [],
+    };
 
+    const tempMaterialList = [];
+
+    for(let i = 0; i < materialList.value.length; i++) {
+        if(materialList.value[i].queryStatus === 0) {
+            params.epcList.push(materialList.value[i].epc);
+            materialList.value[i].queryStatus = 1;
+            tempMaterialList.push(materialList.value[i]);
+        }
+    }
+        
+    if(params.epcList.length == 0){
+        return;
+    }
+        
+    try {
         const res = await cfStockIn(params);
 
         if (res.errorCode === 0) {
             if (res.datas && res.datas.length > 0) {
-                materialList.value = res.datas;
+                res.datas.forEach(i => {
+                    materialList.value.forEach(j => {
+                        if (j.epc === i.epc) {
+                            j.inventoryName = i.inventoryName;
+                            j.inventoryNo = i.inventoryNo;
+                            j.inventoryType = i.inventoryType;
+                            j.warehouseName = i.warehouseName;
+                            j.positionName = i.positionName;
+                            j.inventoryId = i.inventoryId;
+                            j.queryStatus = 2;
+                            j.selected = false;
+                            j.remarks = i.remarks;
+                        }
+                    });
+                });
                 pagination.total = materialList.value.length;
             } else {
                 materialList.value = [];
@@ -222,6 +278,10 @@ const getList = async () => {
     } catch (error) {
         console.error('获取物料列表API调用失败:', error);
         showNotify({ type: 'danger', message: '获取物料列表API调用失败' });
+        // 处理查询失败的物料
+        tempMaterialList.forEach(item => {
+            item.queryStatus = 0;
+        });
     } finally {
         loading.value = false;
     }
@@ -240,7 +300,7 @@ const generateCFStockIn = async params => {
             
             showNotify({ type: 'success', message: '入库申请已完成,还料任务已创建!' });
             // 跳转回主页
-            router.push('/home');
+            router.push('/');
         } else {
             showNotify({ type: 'danger', message: res.errorMessage });
         }
@@ -259,8 +319,25 @@ const addEpc = data => {
     const newEpcs = data.map(item => item.epc);
     
     // 将新epc添加到临时数组中(使用Set去重)
-    const uniqueEpcs = [...new Set([...tempEpcs.value, ...newEpcs])];
-    tempEpcs.value = uniqueEpcs;
+    const uniqueEpcs = new Set([...newEpcs]);
+
+    if(newEpcs != null && newEpcs.length > 0) {
+        newEpcs.forEach(item => {
+            let exist = false;
+            for(let i =0; i < materialList.value.length; i++) {
+                if(materialList.value[i].epc === item) {
+                    exist = true;
+                    break;
+                }
+            }
+            if(exist == false) {
+                materialList.value.push({
+                    epc: item,
+                    queryStatus: 0, // 0: 未查询, 1: 查询中, 2: 已查询, 3: 未查询到
+                });
+            }
+        });
+    }
 };
 
 onMounted(() => {
@@ -277,12 +354,15 @@ onMounted(() => {
     timer = setInterval(() => {
         // 只有当临时数组有数据时才执行getList
         // 将临时数组的数据赋值给epcs
-        epcs.value = [...tempEpcs.value];
         // 执行获取列表
+
+        //addEpc([{
+        //    'epc': 'FFF000000000000000000001',
+        // 'epc': 'AAA000000000000000000002',
+        //}]);
+
         getList();
-        // 清空临时数组
-        tempEpcs.value = [];
-    }, 3000);
+    }, 1000);
 });
 
 onUnmounted(() => {
@@ -293,6 +373,30 @@ onUnmounted(() => {
         timer = null;
     }
 });
+
+
+// 不识别的数据统计
+const unrecognizedCount = computed(() => {
+    return materialList.value.filter(item => item.inventoryId == null).length;
+});
+
+const handleSelect = item => {
+    if(item.remarks === '不在库'){
+        item.selected = !item.selected;
+    }
+};
+
+const enterConfirmVisible = ref(false);
+
+const enterConfirm = () => {
+    enterConfirmVisible.value = false;
+    
+    // 调用开门操作
+    gateController('SHOTOPEN');
+            
+    // 跳转回主页
+    router.push('/');
+};
 </script>
 
 <style scoped>
@@ -429,7 +533,8 @@ onUnmounted(() => {
   left: 10px;
   width: 36px;
   height: 36px;
-  background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%);
+  /* background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%); */
+  background: linear-gradient(135deg, rgb(86, 236, 17) 0%, #28ea0a 100%);
   border-radius: 50%;
   display: flex;
   align-items: center;

+ 8 - 1
src/stock-out/MaterialInOutConfirm.vue

@@ -353,16 +353,19 @@ const handleLeave = async () => {
     }
 };
 
-// 获取扫描到的领料数据
+// 扫描到EPC以后,获取领料的数据
 const getStockOutList = async () => {
     const params = {
         epcList: [],
     };
 
+    const tempMaterialList = [];
+
     for(let i = 0; i < materialList.value.length; i++) {
         if(materialList.value[i].queryStatus === 0) {
             params.epcList.push(materialList.value[i].epc);
             materialList.value[i].queryStatus = 1;
+            tempMaterialList.push(materialList.value[i]);
         }
     }
 
@@ -402,6 +405,10 @@ const getStockOutList = async () => {
     } catch (error) {
         console.error('获取扫描到的领料数据API调用失败:', error);
         showNotify({ type: 'danger', message: '获取扫描到的领料数据API调用失败' });
+        // 处理查询失败的物料
+        tempMaterialList.forEach(item => {
+            item.queryStatus = 0;
+        });
     } finally {
         loading.value = false;
     }

+ 1 - 1
src/stock-out/OrderPicking.vue

@@ -566,7 +566,7 @@ const handleCompleteConfirm = () => {
     // 调用开门操作
     gateController('SHOTOPEN');
     completeModalVisible.value = false;
-    router.push('/home');
+    router.push('/');
     // showToast('领料申请已完成,配送任务已创建!');
 };
 

+ 1 - 1
src/stock-out/OutboundConfirm.vue

@@ -230,7 +230,7 @@ const handleLeave = async () => {
         if (res.errorCode === 0) {
             gateController('SHOTOPEN');
             showNotify({ type: 'success', message: '领料离开成功' });
-            router.push('/home');
+            router.push('/');
         } else {
             showNotify({ type: 'danger', message: res.errorMessage });
         }