From 1ef08126ca554a8cd4b9ba47d19dc3b790e2c018 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 19 五月 2026 17:21:19 +0800
Subject: [PATCH] Merge branch 'dev-new_pro_OA' of http://114.132.189.42:9002/r/product-inventory-management into dev-new_pro_OA

---
 src/views/productionManagement/productStructure/Detail/index.vue |  170 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 142 insertions(+), 28 deletions(-)

diff --git a/src/views/productionManagement/productStructure/Detail/index.vue b/src/views/productionManagement/productStructure/Detail/index.vue
index 6734830..a7f6b6b 100644
--- a/src/views/productionManagement/productStructure/Detail/index.vue
+++ b/src/views/productionManagement/productStructure/Detail/index.vue
@@ -64,6 +64,7 @@
                                filterable
                                clearable
                                style="width: 100%"
+                               @change="value => handleProcessChange(row, value)"
                                :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)">
                       <el-option v-for="item in dataValue.processOptions"
                                  :key="item.id"
@@ -85,6 +86,7 @@
                                      :step="1"
                                      controls-position="right"
                                      style="width: 100%"
+                                     @change="handleUnitQuantityChange"
                                      :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" />
                   </el-form-item>
                 </template>
@@ -102,7 +104,7 @@
                                      :step="1"
                                      controls-position="right"
                                      style="width: 100%"
-                                     :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)" />
+                                     :disabled="true" />
                   </el-form-item>
                 </template>
               </el-table-column>
@@ -148,6 +150,7 @@
     </el-table>
     <product-select-dialog v-if="dataValue.showProductDialog"
                            v-model:model-value="dataValue.showProductDialog"
+                           :single="true"
                            @confirm="handleProduct" />
   </div>
 </template>
@@ -161,7 +164,10 @@
     reactive,
     ref,
   } from "vue";
-  import { queryList, add } from "@/api/productionManagement/productStructure.js";
+  import {
+    queryList,
+    addBomDetail,
+  } from "@/api/productionManagement/productStructure.js";
   import { listProcessBom } from "@/api/productionManagement/productionOrder.js";
   import { list } from "@/api/productionManagement/productionProcess";
   import { ElMessage } from "element-plus";
@@ -212,6 +218,113 @@
     isEdit: false,
   });
 
+  const normalizeListData = (source: any) => {
+    if (Array.isArray(source)) {
+      return source;
+    }
+    if (Array.isArray(source?.records)) {
+      return source.records;
+    }
+    return [];
+  };
+
+  const getProcessOptionById = (id: any) => {
+    if (id === undefined || id === null || id === "") {
+      return null;
+    }
+    return (
+      normalizeListData(dataValue.processOptions).find(
+        option => String(option.id) === String(id)
+      ) || null
+    );
+  };
+
+  const syncProcessOperationFields = (item: any) => {
+    const processId = item.processId ?? item.operationId ?? "";
+    if (!processId) {
+      item.processId = "";
+      item.operationId = "";
+      item.processName = "";
+      item.operationName = "";
+      return;
+    }
+
+    const option = getProcessOptionById(processId);
+    const processName =
+      option?.name || item.processName || item.operationName || "";
+
+    item.processId = processId;
+    item.operationId = processId;
+    item.processName = processName;
+    item.operationName = processName;
+  };
+
+  const normalizeTreeData = (items: any[]) => {
+    items.forEach((item: any) => {
+      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: any) => {
+    const numberValue = Number(value);
+    if (!Number.isFinite(numberValue)) {
+      return 0;
+    }
+    return Number(numberValue.toFixed(2));
+  };
+
+  const syncDemandedQuantityTree = (
+    items: any[],
+    parentDemandedQuantity: number | null = null
+  ) => {
+    items.forEach((item: any) => {
+      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 (!isOrderPage.value) {
+      return;
+    }
+
+    syncDemandedQuantityTree(dataValue.dataList);
+  };
+
+  const buildSubmitTree = (items: any[]) => {
+    return items.map((item: any) => {
+      const current = { ...item };
+      syncProcessOperationFields(current);
+      current.children = Array.isArray(current.children)
+        ? buildSubmitTree(current.children)
+        : [];
+      return current;
+    });
+  };
+
+  const handleProcessChange = (row: any, value: any) => {
+    row.processId = value || "";
+    syncProcessOperationFields(row);
+  };
+
+  const handleUnitQuantityChange = () => {
+    recalculateDemandedQuantities();
+  };
+
   const tableData = reactive([
     {
       productName: "",
@@ -231,37 +344,31 @@
       // 璁㈠崟鎯呭喌锛氫娇鐢ㄨ鍗曠殑浜у搧缁撴瀯鎺ュ彛
       const { data } = await listProcessBom({ orderId: routeOrderId.value });
       dataValue.dataList = (data as any) || [];
+      normalizeTreeData(dataValue.dataList);
+      recalculateDemandedQuantities();
     } else {
       // 闈炶鍗曟儏鍐碉細浣跨敤鍘熸潵鐨勬帴鍙�
       const { data } = await queryList(routeId.value);
       dataValue.dataList = (data as any) || [];
-      // 涓烘墍鏈夐」鍙婂叾瀛愰」璁剧疆name灞炴��
-      const setNameRecursively = (items: any[]) => {
-        items.forEach((item: any) => {
-          item.tempId = item.id;
-          item.processName =
-            dataValue.processOptions.find(option => option.id === item.processId)
-              ?.name || "";
-          if (item.children && item.children.length > 0) {
-            setNameRecursively(item.children);
-          }
-        });
-      };
-      setNameRecursively(dataValue.dataList);
+      console.log(dataValue);
+      normalizeTreeData(dataValue.dataList);
       console.log(dataValue.dataList, "dataValue.dataList");
     }
   };
 
   const fetchProcessOptions = async () => {
-    const { data } = await list();
-    dataValue.processOptions = data as any;
+    const { data } = await list({});
+    console.log(data, "dataValue.dataList");
+    dataValue.processOptions = normalizeListData(data);
   };
 
   const handleProduct = (row: any) => {
-    if (row?.length > 1) {
-      ElMessage.error("鍙兘閫夋嫨涓�涓骇鍝�");
+    if (!Array.isArray(row) || row.length === 0) {
+      ElMessage.warning("璇烽�夋嫨涓�涓骇鍝�");
+      return;
     }
-    const productData = row[0];
+    // 鍙厑璁镐竴涓細濡傛灉涓婃父杩斿洖浜嗗涓紝榛樿浣跨敤鏈�鍚庝竴娆¢�夋嫨骞惰鐩栧綋鍓嶅��
+    const productData = row[row.length - 1];
 
     //  鏈�澶栧眰缁勪欢涓紝涓庡綋鍓嶄骇鍝佺浉鍚岀殑浜у搧鍙兘鏈変竴涓�
     const isTopLevel = dataValue.dataList.some(
@@ -371,19 +478,19 @@
 
   const submit = () => {
     dataValue.loading = true;
+    normalizeTreeData(dataValue.dataList);
+    recalculateDemandedQuantities();
 
     // 鍏堣繘琛岃〃鍗曟牎楠�
     const valid = validateAll();
     console.log(dataValue.dataList, "dataValue.dataList");
     if (valid) {
-      add({
+      addBomDetail({
         bomId: routeId.value,
-        children: dataValue.dataList || [],
+        children: buildSubmitTree(dataValue.dataList || []),
       })
         .then(res => {
-          router.push({
-            path: "/productionManagement/productionManagement/productStructure/index",
-          });
+          router.go(-1);
           ElMessage.success("淇濆瓨鎴愬姛");
           dataValue.loading = false;
         })
@@ -441,13 +548,16 @@
           productModelId: undefined,
           processId: "",
           processName: "",
-          unitQuantity: 0,
+          operationId: "",
+          operationName: "",
+          unitQuantity: 1,
           demandedQuantity: 0,
           unit: "",
           children: [],
 
           tempId: new Date().getTime(),
         });
+        recalculateDemandedQuantities();
         return;
       }
       addchildItem(item, tempId);
@@ -467,12 +577,16 @@
         model: undefined,
         productModelId: undefined,
         processId: "",
-        unitQuantity: 0,
+        processName: "",
+        operationId: "",
+        operationName: "",
+        unitQuantity: 1,
         demandedQuantity: 0,
         children: [],
         unit: "",
         tempId: new Date().getTime(),
       });
+      recalculateDemandedQuantities();
       return true;
     }
     if (item.children && item.children.length > 0) {
@@ -518,4 +632,4 @@
     await fetchProcessOptions();
     await fetchData();
   });
-</script>
\ No newline at end of file
+</script>

--
Gitblit v1.9.3