From 2e36be622d174bb25a9ebdf500e38cd8585593db Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期四, 13 八月 2026 17:48:58 +0800
Subject: [PATCH] fix: 修改接口调用,调整列表查询参数以支持无订单情况

---
 src/views/productionManagement/processRoute/processRouteItem/index.vue |  518 +++++++++++++++++---------------------------------------
 1 files changed, 160 insertions(+), 358 deletions(-)

diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index eaf6397..24b9899 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -47,16 +47,45 @@
             <span class="info-value">{{ routeInfo.quantity || '-' }}</span>
           </div>
         </div>
-        <div class="info-item full-width"
-             v-if="routeInfo.description">
+        <div class="info-item">
           <div class="info-label-wrapper">
-            <span class="info-label">鎻忚堪</span>
+            <span class="info-label">澶囨敞</span>
           </div>
           <div class="info-value-wrapper">
             <span class="info-value">{{ routeInfo.description }}</span>
           </div>
         </div>
       </div>
+    </el-card>
+    <!-- 闄勪欢妯″潡 -->
+    <div v-if="pageType === 'order'"
+         class="section-header">
+      <div class="section-title">闄勪欢</div>
+    </div>
+    <el-card v-if="pageType === 'order'"
+             class="attachment-card"
+             shadow="hover"
+             style="margin-top: 10px; margin-bottom: 20px;">
+      <el-table :data="attachmentTableData"
+                border
+                class="attachment-table">
+        <el-table-column label="闄勪欢鍚嶇О"
+                         prop="originalFilename"
+                         show-overflow-tooltip />
+        <el-table-column fixed="right"
+                         label="鎿嶄綔"
+                         width="200"
+                         align="center">
+          <template #default="scope">
+            <el-button link
+                       type="primary"
+                       size="small"
+                       @click="downloadAttachmentFile(scope.row.downloadURL)">
+              涓嬭浇
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
     </el-card>
     <!-- 琛ㄦ牸瑙嗗浘 -->
     <div v-if="viewMode === 'table'"
@@ -236,6 +265,12 @@
           缂栬緫
         </el-button>
         <el-button v-if="bomDataValue.isEdit"
+                   type="primary"
+                   plain
+                   @click="addBomItem()">
+          娣诲姞鐗╂枡
+        </el-button>
+        <el-button v-if="bomDataValue.isEdit"
                    @click="cancelEditBom">
           鍙栨秷
         </el-button>
@@ -258,8 +293,6 @@
                    :model="bomDataValue">
             <el-table :data="bomDataValue.dataList"
                       row-key="tempId"
-                      default-expand-all
-                      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
                       style="width: 100%">
               <el-table-column prop="productName"
                                label="浜у搧" />
@@ -272,7 +305,7 @@
                     <el-select v-model="row.model"
                                placeholder="璇烽�夋嫨瑙勬牸"
                                clearable
-                               :disabled="!bomDataValue.isEdit || bomDataValue.dataList.some(item => (item).tempId === row.tempId)"
+                               :disabled="!bomDataValue.isEdit"
                                style="width: 100%"
                                @visible-change="(v) => { if (v) openBomDialog(row.tempId) }">
                       <el-option v-if="row.model"
@@ -286,7 +319,7 @@
                                label="娑堣�楀伐搴�">
                 <template #default="{ row }">
                   <el-form-item v-if="pageType === 'order' && bomDataValue.isEdit"
-                                :rules="bomDataValue.dataList.some(item => (item).tempId === row.tempId) ? [] : [{ required: true, message: '璇烽�夋嫨娑堣�楀伐搴�', trigger: 'change' }]"
+                                :rules="[{ required: true, message: '璇烽�夋嫨娑堣�楀伐搴�', trigger: 'change' }]"
                                 style="margin: 0">
                     <el-select v-model="row.processId"
                                placeholder="璇烽�夋嫨"
@@ -294,7 +327,7 @@
                                clearable
                                style="width: 100%"
                                @change="value => handleBomProcessChange(row, value)"
-                               :disabled="!bomDataValue.isEdit || bomDataValue.dataList.some(item => (item).tempId === row.tempId)">
+                               :disabled="!bomDataValue.isEdit">
                       <el-option v-for="item in bomDataValue.processOptions"
                                  :key="item.id"
                                  :label="item.name"
@@ -303,67 +336,14 @@
                   </el-form-item>
                 </template>
               </el-table-column>
-              <el-table-column prop="unitQuantity"
-                               label="鍗曚綅浜у嚭鎵�闇�鏁伴噺">
-                <template #default="{ row }">
-                  <el-form-item v-if="pageType === 'order' && bomDataValue.isEdit"
-                                :rules="[{ required: true, message: '璇疯緭鍏ュ崟浣嶄骇鍑烘墍闇�鏁伴噺', trigger: ['blur','change'] }]"
-                                style="margin: 0">
-                    <el-input-number v-model="row.unitQuantity"
-                                     :min="0"
-                                     :precision="2"
-                                     :step="1"
-                                     controls-position="right"
-                                     style="width: 100%"
-                                     @change="handleUnitQuantityChange"
-                                     :disabled="!bomDataValue.isEdit || bomDataValue.dataList.some(item => (item).tempId === row.tempId)" />
-                  </el-form-item>
-                </template>
-              </el-table-column>
-              <el-table-column v-if="pageType === 'order'"
-                               prop="demandedQuantity"
-                               label="闇�姹傛�婚噺">
-                <template #default="{ row }">
-                  <el-form-item v-if="pageType === 'order' && bomDataValue.isEdit"
-                                :rules="[{ required: true, message: '璇疯緭鍏ラ渶姹傛�婚噺', trigger: ['blur','change'] }]"
-                                style="margin: 0">
-                    <el-input-number v-model="row.demandedQuantity"
-                                     :min="0"
-                                     :precision="2"
-                                     :step="1"
-                                     controls-position="right"
-                                     style="width: 100%"
-                                     :disabled="true" />
-                  </el-form-item>
-                </template>
-              </el-table-column>
-              <el-table-column prop="unit"
-                               label="鍗曚綅">
-                <template #default="{ row }">
-                  <el-form-item v-if="pageType === 'order' && bomDataValue.isEdit"
-                                :rules="[{ required: true, message: '璇疯緭鍏ュ崟浣�', trigger: ['blur','change'] }]"
-                                style="margin: 0">
-                    <el-input v-model="row.unit"
-                              placeholder="璇疯緭鍏ュ崟浣�"
-                              clearable
-                              :disabled="!bomDataValue.isEdit || bomDataValue.dataList.some(item => (item).tempId === row.tempId)" />
-                  </el-form-item>
-                </template>
-              </el-table-column>
               <el-table-column label="鎿嶄綔"
                                fixed="right"
-                               width="200"
+                               width="100"
                                v-if="pageType === 'order' && bomDataValue.isEdit">
                 <template #default="{ row }">
-                  <el-button v-if="bomDataValue.isEdit && !bomDataValue.dataList.some(item => (item).tempId === row.tempId)"
-                             type="danger"
+                  <el-button type="danger"
                              text
                              @click="removeBomItem(row.tempId)">鍒犻櫎
-                  </el-button>
-                  <el-button v-if="bomDataValue.isEdit"
-                             type="primary"
-                             text
-                             @click="addBomItem(row.tempId)">娣诲姞
                   </el-button>
                 </template>
               </el-table-column>
@@ -382,6 +362,18 @@
                          v-model="bomDataValue.showProductDialog"
                          :single="true"
                          @confirm="handleBomProduct" />
+    <!-- 涓婁紶缁勪欢寮圭獥 -->
+    <el-dialog v-model="uploadDialogVisible"
+               title="涓婁紶闄勪欢"
+               width="50%"
+               @close="closeAttachmentUpload">
+      <AttachmentUpload v-model:file-list="newFileList" />
+      <template #footer>
+        <el-button @click="saveAttachmentUpload"
+                   type="primary">淇濆瓨</el-button>
+        <el-button @click="closeAttachmentUpload">鍏抽棴</el-button>
+      </template>
+    </el-dialog>
     <!-- 鏂板/缂栬緫寮圭獥 -->
     <el-dialog v-model="dialogVisible"
                :title="operationType === 'add' ? '鏂板宸ヨ壓璺嚎椤圭洰' : '缂栬緫宸ヨ壓璺嚎椤圭洰'"
@@ -518,6 +510,12 @@
     queryList2,
     add2,
   } from "@/api/productionManagement/productStructure.js";
+  import AttachmentUpload from "@/components/AttachmentUpload/file/index.vue";
+  import {
+    attachmentList,
+    deleteAttachment,
+    createAttachment,
+  } from "@/api/basicData/storageAttachment.js";
 
   import { useRoute } from "vue-router";
   import { ElMessageBox, ElMessage } from "element-plus";
@@ -530,6 +528,7 @@
   const orderId = computed(() => route.query.orderId);
   const pageType = computed(() => route.query.type);
   const editable = computed(() => route.query.editable !== "false");
+  const technologyRoutingId = computed(() => route.query.technologyRoutingId);
 
   const tableLoading = ref(false);
   const tableData = ref([]);
@@ -548,7 +547,66 @@
     bomNo: "",
     description: "",
     quantity: 0,
+    technologyRoutingId: "",
   });
+
+  // 闄勪欢鐩稿叧
+  const attachmentTableData = ref([]);
+  const uploadDialogVisible = ref(false);
+  const newFileList = ref([]);
+
+  const getAttachmentList = () => {
+    if (!technologyRoutingId.value) return;
+    attachmentList({
+      recordType: "technology_routing",
+      recordId: technologyRoutingId.value,
+    }).then(res => {
+      attachmentTableData.value = (res && res.data) || [];
+    });
+  };
+
+  const handleUploadAttachment = () => {
+    uploadDialogVisible.value = true;
+  };
+
+  const saveAttachmentUpload = async () => {
+    if (newFileList.value.length > 0) {
+      createAttachment({
+        application: "file",
+        recordType: "technology_routing",
+        recordId: technologyRoutingId.value,
+        storageBlobDTOs: [...newFileList.value, ...attachmentTableData.value],
+      })
+        .then(res => {
+          if (res && res.code === 200) {
+            proxy?.$modal?.msgSuccess("涓婁紶鎴愬姛");
+            newFileList.value = [];
+            getAttachmentList();
+          }
+        })
+        .finally(() => {
+          uploadDialogVisible.value = false;
+        });
+    }
+  };
+
+  const closeAttachmentUpload = () => {
+    newFileList.value = [];
+    uploadDialogVisible.value = false;
+  };
+
+  const handleDeleteAttachment = async row => {
+    deleteAttachment([row.storageAttachmentId]).then(res => {
+      if (res && res.code === 200) {
+        proxy?.$modal?.msgSuccess("鍒犻櫎鎴愬姛");
+        getAttachmentList();
+      }
+    });
+  };
+
+  const downloadAttachmentFile = url => {
+    window.open(url, "_blank");
+  };
 
   const processOptions = ref([]);
   const showProductSelectDialog = ref(false);
@@ -680,6 +738,7 @@
       bomId: route.query.bomId || "",
       description: route.query.description || "",
       quantity: route.query.quantity || 0,
+      technologyRoutingId: route.query.technologyRoutingId || "",
       status: !(route.query.status == 1 || route.query.status === "false"),
     };
     bomTableData.value[0].productName = routeInfo.value.productName;
@@ -1080,60 +1139,11 @@
     item.operationName = processName;
   };
 
-  const normalizeTreeData = items => {
+  const normalizeBomData = items => {
     items.forEach(item => {
       item.tempId = item.tempId || item.id || `${Date.now()}_${Math.random()}`;
       syncProcessOperationFields(item);
-      if (Array.isArray(item.children) && item.children.length > 0) {
-        normalizeTreeData(item.children);
-      }
     });
-  };
-
-  const toQuantityNumber = value => {
-    const numberValue = Number(value);
-    if (!Number.isFinite(numberValue)) {
-      return 0;
-    }
-    return Number(numberValue.toFixed(2));
-  };
-
-  const syncDemandedQuantityTree = (items, parentDemandedQuantity = null) => {
-    items.forEach(item => {
-      if (parentDemandedQuantity !== null) {
-        item.demandedQuantity = toQuantityNumber(
-          parentDemandedQuantity * toQuantityNumber(item.unitQuantity)
-        );
-      }
-
-      if (Array.isArray(item.children) && item.children.length > 0) {
-        syncDemandedQuantityTree(
-          item.children,
-          toQuantityNumber(item.demandedQuantity)
-        );
-      }
-    });
-  };
-
-  const recalculateDemandedQuantities = () => {
-    if (pageType.value !== "order") {
-      return;
-    }
-
-    const rootDemandedQuantity = routeInfo.value.quantity;
-    if (
-      rootDemandedQuantity === undefined ||
-      rootDemandedQuantity === null ||
-      rootDemandedQuantity === ""
-    ) {
-      syncDemandedQuantityTree(bomDataValue.value.dataList);
-      return;
-    }
-
-    syncDemandedQuantityTree(
-      bomDataValue.value.dataList,
-      toQuantityNumber(rootDemandedQuantity)
-    );
   };
 
   const processChange = value => {
@@ -1146,36 +1156,9 @@
     });
   };
 
-  const findSiblings = (items, tempId) => {
-    if (!items || items.length === 0) return null;
-    // 妫�鏌ュ綋鍓嶅眰绾�
-    if (items.some(item => item.tempId === tempId)) {
-      return items;
-    }
-    // 閫掑綊鏌ユ壘瀛愮骇
-    for (const item of items) {
-      if (item.children && item.children.length > 0) {
-        const result = findSiblings(item.children, tempId);
-        if (result) return result;
-      }
-    }
-    return null;
-  };
-
   const handleBomProcessChange = (row, value) => {
     row.processId = value || "";
     syncProcessOperationFields(row);
-    
-    // 妫�鏌ュ悓涓�灞傜骇鏄惁宸茬粡鏈夊叾浠栦笉鍚岀殑宸ュ簭琚�変腑
-    const siblings = findSiblings(bomDataValue.value.dataList, row.tempId);
-    if (siblings && value) {
-      const hasDifferentProcess = siblings.some(sibling => {
-        return sibling.tempId !== row.tempId && sibling.processId && sibling.processId !== value;
-      });
-      if (hasDifferentProcess) {
-        ElMessage.warning("鍚屼竴灞傜骇宸插瓨鍦ㄤ笉鍚岀殑宸ュ簭锛岃鍏堢粺涓�宸ュ簭鍚庡啀杩涜淇敼");
-      }
-    }
   };
 
   const openBomDialog = tempId => {
@@ -1190,29 +1173,10 @@
         routeInfo.value.bomId
       );
       bomDataValue.value.dataList = data || [];
-      normalizeTreeData(bomDataValue.value.dataList);
-      recalculateDemandedQuantities();
+      normalizeBomData(bomDataValue.value.dataList);
     } catch (err) {
       console.error("鑾峰彇BOM鏁版嵁澶辫触锛�", err);
     }
-  };
-
-  const childItem = (item, tempId, productData) => {
-    if (item.tempId === tempId) {
-      item.productName = productData.productName;
-      item.model = productData.model;
-      item.productModelId = productData.id;
-      item.unit = productData.unit || "";
-      return true;
-    }
-    if (item.children && item.children.length > 0) {
-      for (let child of item.children) {
-        if (childItem(child, tempId, productData)) {
-          return true;
-        }
-      }
-    }
-    return false;
   };
 
   const handleBomProduct = row => {
@@ -1221,217 +1185,51 @@
       return;
     }
     const productData = row[row.length - 1];
-
-    const isTopLevel = bomDataValue.value.dataList.some(
+    const currentItem = bomDataValue.value.dataList.find(
       item => item.tempId === bomDataValue.value.currentRowName
     );
-    if (isTopLevel) {
-      if (
-        productData.productName === bomTableData.value[0].productName &&
-        productData.model === bomTableData.value[0].model
-      ) {
-        const hasOther = bomDataValue.value.dataList.some(
-          item =>
-            item.tempId !== bomDataValue.value.currentRowName &&
-            item.productName === bomTableData.value[0].productName &&
-            item.model === bomTableData.value[0].model
-        );
-        if (hasOther) {
-          ElMessage.warning("鏈�澶栧眰鍜屽綋鍓嶄骇鍝佷竴鏍风殑涓�绾у彧鑳芥湁涓�涓�");
-          return;
-        }
-      }
+    if (currentItem) {
+      currentItem.productName = productData.productName;
+      currentItem.model = productData.model;
+      currentItem.productModelId = productData.id;
     }
-    bomDataValue.value.dataList.forEach(item => {
-      if (item.tempId === bomDataValue.value.currentRowName) {
-        item.productName = productData.productName;
-        item.model = productData.model;
-        item.productModelId = productData.id;
-        item.unit = productData.unit || "";
-        return;
-      }
-      childItem(item, bomDataValue.value.currentRowName, productData);
-    });
     bomDataValue.value.showProductDialog = false;
   };
 
   const removeBomItem = tempId => {
-    const topIndex = bomDataValue.value.dataList.findIndex(
+    const index = bomDataValue.value.dataList.findIndex(
       item => item.tempId === tempId
     );
-    if (topIndex !== -1) {
-      bomDataValue.value.dataList.splice(topIndex, 1);
-      return;
+    if (index !== -1) {
+      bomDataValue.value.dataList.splice(index, 1);
     }
-
-    const delchildItem = (items, tempId) => {
-      for (let i = 0; i < items.length; i++) {
-        const item = items[i];
-        if (item.tempId === tempId) {
-          items.splice(i, 1);
-          return true;
-        }
-        if (item.children && item.children.length > 0) {
-          if (delchildItem(item.children, tempId)) {
-            return true;
-          }
-        }
-      }
-      return false;
-    };
-
-    bomDataValue.value.dataList.forEach(item => {
-      if (item.children && item.children.length > 0) {
-        delchildItem(item.children, tempId);
-      }
-    });
   };
 
-  const handleUnitQuantityChange = () => {
-    recalculateDemandedQuantities();
-  };
-
-  const addchildItem = (item, tempId) => {
-    if (item.tempId === tempId) {
-      if (!item.children) {
-        item.children = [];
-      }
-      item.children.push({
-        parentId: item.id || "",
-        parentTempId: item.tempId || "",
-        productName: "",
-        productId: "",
-        model: undefined,
-        productModelId: undefined,
-        processId: "",
-        processName: "",
-        [pageType.value === "order" ? "technologyOperationId" : "operationId"]:
-          "",
-        operationName: "",
-        unitQuantity: 1,
-        demandedQuantity: 0,
-        children: [],
-        unit: "",
-        tempId: new Date().getTime(),
-      });
-      recalculateDemandedQuantities();
-      return true;
-    }
-    if (item.children && item.children.length > 0) {
-      for (let child of item.children) {
-        if (addchildItem(child, tempId)) {
-          return true;
-        }
-      }
-    }
-    return false;
-  };
-
-  const addBomItem = tempId => {
-    bomDataValue.value.dataList.forEach(item => {
-      if (item.tempId === tempId) {
-        if (!item.children) {
-          item.children = [];
-        }
-        item.children.push({
-          parentId: item.id || "",
-          parentTempId: item.tempId || "",
-          productName: "",
-          productId: "",
-          model: undefined,
-          productModelId: undefined,
-          processId: "",
-          processName: "",
-          [pageType.value === "order" ? "technologyOperationId" : "operationId"]:
-            "",
-          operationName: "",
-          unitQuantity: 1,
-          demandedQuantity: 0,
-          unit: "",
-          children: [],
-          tempId: new Date().getTime(),
-        });
-        recalculateDemandedQuantities();
-        return;
-      }
-      addchildItem(item, tempId);
+  const addBomItem = () => {
+    bomDataValue.value.dataList.push({
+      productName: "",
+      model: undefined,
+      productModelId: undefined,
+      processId: "",
+      processName: "",
+      technologyOperationId: "",
+      operationName: "",
+      tempId: `${Date.now()}_${Math.random()}`,
     });
   };
 
   const validateAllBom = () => {
-    let isValid = true;
-    const isOrderPage = pageType.value === "order";
-
-    const validateItem = (item, isTopLevel = false) => {
-      if (!item.model) {
-        ElMessage.error("璇烽�夋嫨瑙勬牸");
-        isValid = false;
-        return;
+    for (const item of bomDataValue.value.dataList) {
+      if (!item.productModelId) {
+        ElMessage.error("璇烽�夋嫨鐗╂枡瑙勬牸");
+        return false;
       }
-      if (!isTopLevel && !item.processId) {
+      if (!item.processId) {
         ElMessage.error("璇烽�夋嫨娑堣�楀伐搴�");
-        isValid = false;
-        return;
+        return false;
       }
-      if (!item.unitQuantity) {
-        ElMessage.error("璇疯緭鍏ュ崟浣嶄骇鍑烘墍闇�鏁伴噺");
-        isValid = false;
-        return;
-      }
-      if (isOrderPage && !item.demandedQuantity) {
-        ElMessage.error("璇疯緭鍏ラ渶姹傛�婚噺");
-        isValid = false;
-        return;
-      }
-
-      if (item.children && item.children.length > 0) {
-        item.children.forEach(child => {
-          validateItem(child, false);
-        });
-      }
-    };
-
-    // 鏍¢獙鍚屼竴灞傜骇鐨勫伐搴忔槸鍚︿竴鑷�
-    const validateProcessConsistency = (items) => {
-      if (!items || items.length === 0) return;
-
-      // 妫�鏌ュ綋鍓嶅眰绾�
-      const processes = items.filter(item => item.processId).map(item => item.processId);
-      if (processes.length > 1) {
-        const uniqueProcesses = [...new Set(processes)];
-        if (uniqueProcesses.length > 1) {
-          ElMessage.error("鍚屼竴灞傜骇鐨勫伐搴忓繀椤讳竴鑷�");
-          isValid = false;
-          return;
-        }
-      }
-
-      // 閫掑綊妫�鏌ュ瓙绾�
-      items.forEach(item => {
-        if (item.children && item.children.length > 0) {
-          validateProcessConsistency(item.children);
-        }
-      });
-    };
-
-    bomDataValue.value.dataList.forEach(item => {
-      validateItem(item, true);
-    });
-
-    validateProcessConsistency(bomDataValue.value.dataList);
-
-    return isValid;
-  };
-
-  const buildSubmitTree = items => {
-    return items.map(item => {
-      const current = { ...item };
-      syncProcessOperationFields(current);
-      current.children = Array.isArray(current.children)
-        ? buildSubmitTree(current.children)
-        : [];
-      return current;
-    });
+    }
+    return true;
   };
 
   const cancelEditBom = () => {
@@ -1441,17 +1239,18 @@
 
   const handleSaveBom = () => {
     bomDataValue.value.loading = true;
-    console.log(bomDataValue.value.dataList, "bomDataValue.value.dataList");
-
-    normalizeTreeData(bomDataValue.value.dataList);
-    recalculateDemandedQuantities();
+    normalizeBomData(bomDataValue.value.dataList);
 
     const valid = validateAllBom();
     if (valid) {
       add2({
-        // bomId: Number(routeInfo.value.bomId),
         productionOrderBomId: Number(routeInfo.value.bomId) || null,
-        children: buildSubmitTree(bomDataValue.value.dataList || []),
+        productionOrderId: Number(orderId.value) || null,
+        detailList: bomDataValue.value.dataList.map(item => ({
+          id: item.id || undefined,
+          productModelId: item.productModelId,
+          technologyOperationId: item.technologyOperationId || item.processId,
+        })),
       })
         .then(() => {
           ElMessage.success("BOM淇濆瓨鎴愬姛");
@@ -1474,6 +1273,9 @@
     getList();
     getProcessList();
     fetchBomData();
+    if (pageType.value === "order") {
+      getAttachmentList();
+    }
   };
 
   onMounted(() => {

--
Gitblit v1.9.3