From ff1e38350372a20b673c211b88843c48d96b48ca Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 19 三月 2026 10:16:33 +0800
Subject: [PATCH] 工艺路线和BOM修改

---
 src/views/productionManagement/productStructure/Detail/index.vue       |   21 -
 src/views/productionManagement/processRoute/index.vue                  |    9 
 src/views/productionManagement/processRoute/New.vue                    |  315 +++++++++++++------------
 src/views/productionManagement/processRoute/processRouteItem/index.vue |  147 +++++++-----
 src/views/productionManagement/processRoute/Edit.vue                   |  174 ++++++-------
 src/views/productionManagement/productStructure/index.vue              |    3 
 6 files changed, 340 insertions(+), 329 deletions(-)

diff --git a/src/views/productionManagement/processRoute/Edit.vue b/src/views/productionManagement/processRoute/Edit.vue
index 53d8395..4ce5098 100644
--- a/src/views/productionManagement/processRoute/Edit.vue
+++ b/src/views/productionManagement/processRoute/Edit.vue
@@ -8,21 +8,25 @@
                :model="formState"
                label-position="top"
                ref="formRef">
-        <el-form-item label="浜у搧鍚嶇О"
-                      prop="productModelId"
+        <el-form-item label="浜у搧绫诲瀷"
+                      prop="dictCode"
                       :rules="[
                 {
                 required: true,
-                message: '璇烽�夋嫨浜у搧',
+                message: '璇烽�夋嫨浜у搧绫诲瀷',
                 trigger: 'change',
               }
             ]">
-          <el-button type="primary"
-                     @click="showProductSelectDialog = true">
-            {{ formState.productName && formState.productModelName 
-              ? `${formState.productName} - ${formState.productModelName}` 
-              : '閫夋嫨浜у搧' }}
-          </el-button>
+          <el-select v-model="formState.dictCode"
+                     placeholder="璇烽�夋嫨浜у搧绫诲瀷"
+                     clearable
+                     style="width: 100%"
+                     @change="handleProductTypeChange">
+            <el-option v-for="item in productTypeOptions"
+                       :key="item.dictCode"
+                       :label="item.dictLabel"
+                       :value="item.dictCode" />
+          </el-select>
         </el-form-item>
         <el-form-item label="BOM"
                       prop="bomId"
@@ -36,7 +40,7 @@
           <el-select v-model="formState.bomId"
                      placeholder="璇烽�夋嫨BOM"
                      clearable
-                     :disabled="!formState.productModelId || bomOptions.length === 0"
+                     :disabled="!formState.dictCode || bomOptions.length === 0"
                      style="width: 100%">
             <el-option v-for="item in bomOptions"
                        :key="item.id"
@@ -50,10 +54,7 @@
                     type="textarea" />
         </el-form-item>
       </el-form>
-      <!-- 浜у搧閫夋嫨寮圭獥 -->
-      <ProductSelectDialog v-model="showProductSelectDialog"
-                           @confirm="handleProductSelect"
-                           single />
+
       <template #footer>
         <div class="dialog-footer">
           <el-button type="primary"
@@ -75,8 +76,8 @@
     watch,
   } from "vue";
   import { update } from "@/api/productionManagement/processRoute.js";
-  import { getByModel } from "@/api/productionManagement/productBom.js";
-  import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+  import { listPage } from "@/api/productionManagement/productBom.js";
+  import { getDicts } from "@/api/system/dict/data.js";
 
   const props = defineProps({
     visible: {
@@ -94,10 +95,8 @@
 
   // 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
   const formState = ref({
-    productId: undefined,
-    productModelId: undefined,
-    productName: "",
-    productModelName: "",
+    dictCode: undefined,
+    dictLabel: "",
     bomId: undefined,
     description: "",
   });
@@ -111,10 +110,48 @@
     },
   });
 
-  const showProductSelectDialog = ref(false);
+  const productTypeOptions = ref([]);
   const bomOptions = ref([]);
 
   let { proxy } = getCurrentInstance();
+
+  // 鑾峰彇浜у搧绫诲瀷瀛楀吀
+  const getProductTypeOptions = () => {
+    getDicts("product_type")
+      .then(res => {
+        if (res.code === 200) {
+          productTypeOptions.value = res.data;
+        }
+      })
+      .catch(err => {
+        console.error("鑾峰彇浜у搧绫诲瀷瀛楀吀澶辫触锛�", err);
+      });
+  };
+
+  // 鏍规嵁浜у搧绫诲瀷鑾峰彇BOM鍒楄〃
+  const getBomListByProductType = async dictCode => {
+    if (!dictCode) {
+      bomOptions.value = [];
+      return;
+    }
+    try {
+      // 浣跨敤listPage鎺ュ彛锛屾牴鎹甦ictCode鏌ヨBOM
+      const res = await listPage({ dictCode });
+      // 澶勭悊杩斿洖鐨凚OM鏁版嵁
+      let bomList = [];
+      if (res.data && res.data.records) {
+        bomList = res.data.records;
+      }
+      bomOptions.value = bomList;
+      if (bomList.length === 0) {
+        proxy.$modal.msgError("璇ヤ骇鍝佺被鍨嬫病鏈塀OM锛岃鍏堝垱寤築OM");
+      }
+    } catch (error) {
+      // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
+      proxy.$modal.msgError("璇ヤ骇鍝佺被鍨嬫病鏈塀OM锛岃鍏堝垱寤築OM");
+      bomOptions.value = [];
+    }
+  };
 
   const closeModal = () => {
     isShow.value = false;
@@ -125,94 +162,42 @@
     if (props.record) {
       formState.value = {
         ...props.record,
-        productId: props.record.productId,
-        productModelId: props.record.productModelId,
-        productName: props.record.productName || "",
-        // 娉ㄦ剰锛歳ecord涓殑瀛楁鏄痬odel锛岄渶瑕佹槧灏勫埌productModelName
-        productModelName:
-          props.record.model || props.record.productModelName || "",
+        dictCode: props.record.dictCode,
+        dictLabel: props.record.dictLabel || "",
         bomId: props.record.bomId,
         description: props.record.description || "",
       };
-      // 濡傛灉鏈変骇鍝佸瀷鍙稩D锛屽姞杞紹OM鍒楄〃
-      if (props.record.productModelId) {
-        loadBomList(props.record.productModelId);
+      // 濡傛灉鏈変骇鍝佺被鍨嬶紝鍔犺浇BOM鍒楄〃
+      if (props.record.dictCode) {
+        getBomListByProductType(props.record.dictCode);
       }
     }
   };
 
-  // 鍔犺浇BOM鍒楄〃
-  const loadBomList = async productModelId => {
-    if (!productModelId) {
-      bomOptions.value = [];
-      return;
-    }
-    try {
-      const res = await getByModel(productModelId);
-      // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
-      let bomList = [];
-      if (Array.isArray(res)) {
-        bomList = res;
-      } else if (res && res.data) {
-        bomList = Array.isArray(res.data) ? res.data : [res.data];
-      } else if (res && typeof res === "object") {
-        bomList = [res];
+  // 浜у搧绫诲瀷閫夋嫨澶勭悊
+  const handleProductTypeChange = async dictCode => {
+    if (dictCode) {
+      const selectedType = productTypeOptions.value.find(item => item.dictCode === dictCode);
+      if (selectedType) {
+        formState.value.dictLabel = selectedType.dictLabel;
       }
-      bomOptions.value = bomList;
-    } catch (error) {
-      console.error("鍔犺浇BOM鍒楄〃澶辫触锛�", error);
+      // 濡傛灉褰撳墠閫夋嫨鐨凚OM涓嶅湪鏂板垪琛ㄤ腑锛屽垯閲嶇疆BOM閫夋嫨
+      formState.value.bomId = undefined;
+      await getBomListByProductType(dictCode);
+      // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+      proxy.$refs["formRef"]?.validateField("dictCode");
+    } else {
+      formState.value.dictLabel = "";
       bomOptions.value = [];
-    }
-  };
-
-  // 浜у搧閫夋嫨澶勭悊
-  const handleProductSelect = async products => {
-    if (products && products.length > 0) {
-      const product = products[0];
-      // 鍏堟煡璇OM鍒楄〃锛堝繀閫夛級
-      try {
-        const res = await getByModel(product.id);
-        // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
-        let bomList = [];
-        if (Array.isArray(res)) {
-          bomList = res;
-        } else if (res && res.data) {
-          bomList = Array.isArray(res.data) ? res.data : [res.data];
-        } else if (res && typeof res === "object") {
-          bomList = [res];
-        }
-
-        if (bomList.length > 0) {
-          formState.value.productModelId = product.id;
-          formState.value.productName = product.productName;
-          formState.value.productModelName = product.model;
-          // 濡傛灉褰撳墠閫夋嫨鐨凚OM涓嶅湪鏂板垪琛ㄤ腑锛屽垯閲嶇疆BOM閫夋嫨
-          const currentBomExists = bomList.some(
-            bom => bom.id === formState.value.bomId
-          );
-          if (!currentBomExists) {
-            formState.value.bomId = undefined;
-          }
-          bomOptions.value = bomList;
-          showProductSelectDialog.value = false;
-          // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
-          proxy.$refs["formRef"]?.validateField("productModelId");
-        } else {
-          proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
-        }
-      } catch (error) {
-        // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
-        proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
-      }
     }
   };
 
   const handleSubmit = () => {
     proxy.$refs["formRef"].validate(valid => {
       if (valid) {
-        // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰BOM
-        if (!formState.value.productModelId) {
-          proxy.$modal.msgError("璇烽�夋嫨浜у搧");
+        // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佺被鍨嬪拰BOM
+        if (!formState.value.dictCode) {
+          proxy.$modal.msgError("璇烽�夋嫨浜у搧绫诲瀷");
           return;
         }
         if (!formState.value.bomId) {
@@ -250,6 +235,7 @@
   );
 
   onMounted(() => {
+    getProductTypeOptions();
     if (props.visible && props.record) {
       setFormData();
     }
diff --git a/src/views/productionManagement/processRoute/New.vue b/src/views/productionManagement/processRoute/New.vue
index 62c6873..981ae89 100644
--- a/src/views/productionManagement/processRoute/New.vue
+++ b/src/views/productionManagement/processRoute/New.vue
@@ -1,71 +1,67 @@
 <template>
   <div>
-    <el-dialog
-        v-model="isShow"
-        title="鏂板宸ヨ壓璺嚎"
-        width="400"
-        @close="closeModal"
-    >
-      <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
-        <el-form-item
-            label="浜у搧鍚嶇О"
-            prop="productModelId"
-            :rules="[
+    <el-dialog v-model="isShow"
+               title="鏂板宸ヨ壓璺嚎"
+               width="400"
+               @close="closeModal">
+      <el-form label-width="140px"
+               :model="formState"
+               label-position="top"
+               ref="formRef">
+        <el-form-item label="浜у搧绫诲瀷"
+                      prop="dictCode"
+                      :rules="[
                 {
                 required: true,
-                message: '璇烽�夋嫨浜у搧',
+                message: '璇烽�夋嫨浜у搧绫诲瀷',
                 trigger: 'change',
               }
-            ]"
-        >
-          <el-button type="primary" @click="showProductSelectDialog = true">
-            {{ formState.productName && formState.productModelName 
-              ? `${formState.productName} - ${formState.productModelName}` 
-              : '閫夋嫨浜у搧' }}
-          </el-button>
+            ]">
+          <el-select v-model="formState.dictCode"
+                     placeholder="璇烽�夋嫨浜у搧绫诲瀷"
+                     clearable
+                     style="width: 100%"
+                     @change="handleProductTypeChange">
+            <el-option v-for="item in productTypeOptions"
+                       :key="item.dictCode"
+                       :label="item.dictLabel"
+                       :value="item.dictCode" />
+          </el-select>
         </el-form-item>
-
-        <el-form-item
-            label="BOM"
-            prop="bomId"
-            :rules="[
+        <el-form-item label="BOM"
+                      prop="bomId"
+                      :rules="[
                 {
                 required: true,
                 message: '璇烽�夋嫨BOM',
                 trigger: 'change',
               }
-            ]"
-        >
-          <el-select
-              v-model="formState.bomId"
-              placeholder="璇烽�夋嫨BOM"
-              clearable
-              :disabled="!formState.productModelId || bomOptions.length === 0"
-              style="width: 100%"
-          >
-            <el-option
-                v-for="item in bomOptions"
-                :key="item.id"
-                :label="item.bomNo || `BOM-${item.id}`"
-                :value="item.id"
-            />
+            ]">
+          <el-select v-model="formState.bomId"
+                     placeholder="璇烽�夋嫨BOM"
+                     clearable
+                     :disabled="!formState.dictCode || bomOptions.length === 0"
+                     style="width: 100%">
+            <el-option v-for="item in bomOptions"
+                       :key="item.id"
+                       :label="item.bomNo || `BOM-${item.id}`"
+                       :value="item.id" />
           </el-select>
         </el-form-item>
-
-        <el-form-item label="澶囨敞" prop="description">
-          <el-input v-model="formState.description" type="textarea" />
+        <el-form-item label="澶囨敞"
+                      prop="description">
+          <el-input v-model="formState.description"
+                    type="textarea" />
         </el-form-item>
       </el-form>
-      
       <!-- 浜у搧閫夋嫨寮圭獥 -->
-      <ProductSelectDialog
-          v-model="showProductSelectDialog"
-          @confirm="handleProductSelect"
-          single
-      />
+      <ProductSelectDialog v-model="showProductSelectDialog"
+                           @confirm="handleProductSelect"
+                           single />
       <template #footer>
         <div class="dialog-footer">
-          <el-button type="primary" @click="handleSubmit">纭</el-button>
+          <el-button type="primary"
+                     @click="handleSubmit">纭</el-button>
           <el-button @click="closeModal">鍙栨秷</el-button>
         </div>
       </template>
@@ -74,121 +70,142 @@
 </template>
 
 <script setup>
-import {ref, computed, getCurrentInstance} from "vue";
-import {add} from "@/api/productionManagement/processRoute.js";
-import {getByModel} from "@/api/productionManagement/productBom.js";
-import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+  import { ref, computed, getCurrentInstance, onMounted } from "vue";
+  import { add } from "@/api/productionManagement/processRoute.js";
+  import { listPage } from "@/api/productionManagement/productBom.js";
+  import { getDicts } from "@/api/system/dict/data.js";
 
-const props = defineProps({
-  visible: {
-    type: Boolean,
-    required: true,
-  },
-});
+  const props = defineProps({
+    visible: {
+      type: Boolean,
+      required: true,
+    },
+  });
 
-const emit = defineEmits(['update:visible', 'completed']);
+  const emit = defineEmits(["update:visible", "completed"]);
 
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
-const formState = ref({
-  productId: undefined,
-  productModelId: undefined,
-  productName: "",
-  productModelName: "",
-  bomId: undefined,
-  description: '',
-});
-
-const isShow = computed({
-  get() {
-    return props.visible;
-  },
-  set(val) {
-    emit('update:visible', val);
-  },
-});
-
-const showProductSelectDialog = ref(false);
-const bomOptions = ref([]);
-
-let { proxy } = getCurrentInstance()
-
-const closeModal = () => {
-  // 閲嶇疆琛ㄥ崟鏁版嵁
-  formState.value = {
-    productId: undefined,
-    productModelId: undefined,
-    productName: "",
-    productModelName: "",
+  // 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
+  const formState = ref({
+    dictCode: undefined,
+    dictLabel: "",
     bomId: undefined,
-    description: '',
-  };
-  bomOptions.value = [];
-  isShow.value = false;
-};
+    description: "",
+  });
 
-// 浜у搧閫夋嫨澶勭悊
-const handleProductSelect = async (products) => {
-  if (products && products.length > 0) {
-    const product = products[0];
-    // 鍏堟煡璇OM鍒楄〃锛堝繀閫夛級
+  const isShow = computed({
+    get() {
+      return props.visible;
+    },
+    set(val) {
+      emit("update:visible", val);
+    },
+  });
+
+  const productTypeOptions = ref([]);
+  const bomOptions = ref([]);
+
+  let { proxy } = getCurrentInstance();
+
+  // 鑾峰彇浜у搧绫诲瀷瀛楀吀
+  const getProductTypeOptions = () => {
+    getDicts("product_type")
+      .then(res => {
+        if (res.code === 200) {
+          productTypeOptions.value = res.data;
+        }
+      })
+      .catch(err => {
+        console.error("鑾峰彇浜у搧绫诲瀷瀛楀吀澶辫触锛�", err);
+      });
+  };
+
+  // 鏍规嵁浜у搧绫诲瀷鑾峰彇BOM鍒楄〃
+  const getBomListByProductType = async dictCode => {
+    if (!dictCode) {
+      bomOptions.value = [];
+      return;
+    }
     try {
-      const res = await getByModel(product.id);
-      // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
+      // 浣跨敤listPage鎺ュ彛锛屾牴鎹甦ictCode鏌ヨBOM
+      const res = await listPage({ dictCode });
+      // 澶勭悊杩斿洖鐨凚OM鏁版嵁
       let bomList = [];
-      if (Array.isArray(res)) {
-        bomList = res;
-      } else if (res && res.data) {
-        bomList = Array.isArray(res.data) ? res.data : [res.data];
-      } else if (res && typeof res === 'object') {
-        bomList = [res];
+      if (res.data && res.data.records) {
+        bomList = res.data.records;
       }
-      
-      if (bomList.length > 0) {
-        formState.value.productModelId = product.id;
-        formState.value.productName = product.productName;
-        formState.value.productModelName = product.model;
-        formState.value.bomId = undefined; // 閲嶇疆BOM閫夋嫨
-        bomOptions.value = bomList;
-        showProductSelectDialog.value = false;
-        // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
-        proxy.$refs["formRef"]?.validateField('productModelId');
-      } else {
-        proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
+      bomOptions.value = bomList;
+      if (bomList.length === 0) {
+        proxy.$modal.msgError("璇ヤ骇鍝佺被鍨嬫病鏈塀OM锛岃鍏堝垱寤築OM");
       }
     } catch (error) {
       // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
-      proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
+      proxy.$modal.msgError("璇ヤ骇鍝佺被鍨嬫病鏈塀OM锛岃鍏堝垱寤築OM");
+      bomOptions.value = [];
     }
-  }
-};
+  };
 
-const handleSubmit = () => {
-  proxy.$refs["formRef"].validate(valid => {
-    if (valid) {
-      // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰BOM
-      if (!formState.value.productModelId) {
-        proxy.$modal.msgError("璇烽�夋嫨浜у搧");
-        return;
+  const closeModal = () => {
+    // 閲嶇疆琛ㄥ崟鏁版嵁
+    formState.value = {
+      dictCode: undefined,
+      dictLabel: "",
+      bomId: undefined,
+      description: "",
+    };
+    bomOptions.value = [];
+    isShow.value = false;
+  };
+
+  // 浜у搧绫诲瀷閫夋嫨澶勭悊
+  const handleProductTypeChange = async dictCode => {
+    if (dictCode) {
+      const selectedType = productTypeOptions.value.find(
+        item => item.dictCode === dictCode
+      );
+      if (selectedType) {
+        formState.value.dictLabel = selectedType.dictLabel;
       }
-      if (!formState.value.bomId) {
-        proxy.$modal.msgError("璇烽�夋嫨BOM");
-        return;
-      }
-      add(formState.value).then(res => {
-        // 鍏抽棴妯℃�佹
-        isShow.value = false;
-        // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
-        emit('completed');
-        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-      })
+      formState.value.bomId = undefined; // 閲嶇疆BOM閫夋嫨
+      await getBomListByProductType(dictCode);
+      // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+      proxy.$refs["formRef"]?.validateField("dictCode");
+    } else {
+      formState.value.dictLabel = "";
+      bomOptions.value = [];
     }
-  })
-};
+  };
 
+  const handleSubmit = () => {
+    proxy.$refs["formRef"].validate(valid => {
+      if (valid) {
+        // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佺被鍨嬪拰BOM
+        if (!formState.value.dictCode) {
+          proxy.$modal.msgError("璇烽�夋嫨浜у搧绫诲瀷");
+          return;
+        }
+        if (!formState.value.bomId) {
+          proxy.$modal.msgError("璇烽�夋嫨BOM");
+          return;
+        }
+        add(formState.value).then(res => {
+          // 鍏抽棴妯℃�佹
+          isShow.value = false;
+          // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
+          emit("completed");
+          proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+        });
+      }
+    });
+  };
 
-defineExpose({
-  closeModal,
-  handleSubmit,
-  isShow,
-});
+  // 缁勪欢鎸傝浇鏃惰幏鍙栦骇鍝佺被鍨嬪瓧鍏�
+  onMounted(() => {
+    getProductTypeOptions();
+  });
+
+  defineExpose({
+    closeModal,
+    handleSubmit,
+    isShow,
+  });
 </script>
diff --git a/src/views/productionManagement/processRoute/index.vue b/src/views/productionManagement/processRoute/index.vue
index 83d789e..5e58f09 100644
--- a/src/views/productionManagement/processRoute/index.vue
+++ b/src/views/productionManagement/processRoute/index.vue
@@ -77,12 +77,8 @@
       prop: "processRouteCode",
     },
     {
-      label: "浜у搧鍚嶇О",
-      prop: "productName",
-    },
-    {
-      label: "瑙勬牸鍚嶇О",
-      prop: "model",
+      label: "浜у搧绫诲瀷",
+      prop: "dictLabel",
     },
     {
       label: "BOM缂栧彿",
@@ -204,6 +200,7 @@
         productName: row.productName || "",
         model: row.model || "",
         bomNo: row.bomNo || "",
+        dictLabel: row.dictLabel || "",
         bomId: row.bomId || null,
         description: row.description || "",
         type: "route",
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index ce3ee0b..cd9260a 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -16,18 +16,10 @@
         </div>
         <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.productName || '-' }}</span>
-          </div>
-        </div>
-        <div class="info-item">
-          <div class="info-label-wrapper">
-            <span class="info-label">瑙勬牸鍚嶇О</span>
-          </div>
-          <div class="info-value-wrapper">
-            <span class="info-value">{{ routeInfo.model || '-' }}</span>
+            <span class="info-value">{{ routeInfo.dictLabel || '-' }}</span>
           </div>
         </div>
         <div class="info-item">
@@ -71,7 +63,9 @@
               :data="tableData"
               :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
               row-key="id"
+              height="350"
               tooltip-effect="dark"
+              style="margin-bottom: 20px;"
               class="lims-table">
       <el-table-column align="center"
                        label="搴忓彿"
@@ -84,12 +78,6 @@
           {{ getProcessName(scope.row.processId) || '-' }}
         </template>
       </el-table-column>
-      <el-table-column label="浜у搧鍚嶇О"
-                       prop="productName"
-                       min-width="160" />
-      <el-table-column label="瑙勬牸鍚嶇О"
-                       prop="model"
-                       min-width="140" />
       <el-table-column label="鍙傛暟鍒楄〃"
                        min-width="160">
         <template #default="scope">
@@ -99,14 +87,12 @@
                      @click="handleViewParams(scope.row)">鍙傛暟鍒楄〃</el-button>
         </template>
       </el-table-column>
-      <el-table-column label="鍗曚綅"
-                       prop="unit"
-                       width="100" />
       <el-table-column label="鏄惁璐ㄦ"
-                       prop="isQuality"
-                       width="100">
+                       prop="isQuality">
         <template #default="scope">
-          {{scope.row.isQuality ? "鏄�" : "鍚�"}}
+          <el-tag :type="scope.row.isQuality ? 'success' : 'danger'">
+            {{scope.row.isQuality ? '鏄�' : '鍚�' }}
+          </el-tag>
         </template>
       </el-table-column>
       <el-table-column label="鎿嶄綔"
@@ -119,10 +105,6 @@
                      size="small"
                      @click="handleEdit(scope.row)"
                      :disabled="scope.row.isComplete">缂栬緫</el-button>
-          <!-- <el-button type="info"
-                     link
-                     size="small"
-                     @click="handleViewParams(scope.row)">鍙傛暟鍒楄〃</el-button> -->
           <el-button type="danger"
                      link
                      size="small"
@@ -160,20 +142,6 @@
             </div>
             <!-- 浜у搧淇℃伅 -->
             <div class="card-content">
-              <div v-if="item.productName"
-                   class="product-info">
-                <div class="product-name">{{ item.productName }}</div>
-                <div v-if="item.model"
-                     class="product-model">
-                  {{ item.model }}
-                  <!-- <span v-if="item.unit" class="product-unit">{{ item.unit }}</span> -->
-                </div>
-                <el-tag type="primary"
-                        class="product-tag"
-                        v-if="item.isQuality">璐ㄦ</el-tag>
-              </div>
-              <div v-else
-                   class="product-info empty">鏆傛棤浜у搧淇℃伅</div>
             </div>
             <!-- 鎿嶄綔鎸夐挳 -->
             <div class="card-footer">
@@ -196,6 +164,50 @@
         </div>
       </div>
     </template>
+    <div class="section-BOM">
+      <div class="section-header">
+        <div class="section-title">BOM</div>
+      </div>
+      <div>
+        <!-- BOM琛ㄦ牸 -->
+        <el-table :data="bomTableData"
+                  border
+                  :preserve-expanded-content="false"
+                  :default-expand-all="true"
+                  style="width: 100%">
+          <el-table-column type="expand">
+            <template #default="props">
+              <el-table :data="props.row.bomList"
+                        row-key="id"
+                        default-expand-all
+                        :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+                        style="width: 100%">
+                <el-table-column prop="productName"
+                                 label="浜у搧" />
+                <el-table-column prop="model"
+                                 label="瑙勬牸" />
+                <el-table-column prop="processName"
+                                 label="娑堣�楀伐搴�" />
+                <el-table-column prop="unitQuantity"
+                                 label="鍗曚綅浜у嚭鎵�闇�鏁伴噺" />
+                <el-table-column prop="unit"
+                                 label="鍗曚綅" />
+              </el-table>
+            </template>
+          </el-table-column>
+          <el-table-column label="BOM缂栧彿"
+                           prop="bomNo" />
+          <el-table-column label="浜у搧绫诲瀷"
+                           prop="dictLabel" />
+          <!-- <el-table-column label="浜у搧缂栫爜"
+                           prop="productCode" />
+          <el-table-column label="浜у搧鍚嶇О"
+                           prop="productName" />
+          <el-table-column label="瑙勬牸鍨嬪彿"
+                           prop="model" /> -->
+        </el-table>
+      </div>
+    </div>
     <!-- 鏂板/缂栬緫寮圭獥 -->
     <el-dialog v-model="dialogVisible"
                :title="operationType === 'add' ? '鏂板宸ヨ壓璺嚎椤圭洰' : '缂栬緫宸ヨ壓璺嚎椤圭洰'"
@@ -216,22 +228,6 @@
                        :label="process.name"
                        :value="process.id" />
           </el-select>
-        </el-form-item>
-        <el-form-item label="浜у搧鍚嶇О"
-                      prop="productModelId">
-          <el-button type="primary"
-                     @click="showProductSelectDialog = true">
-            {{ form.productName && form.model 
-              ? `${form.productName} - ${form.model}` 
-              : '閫夋嫨浜у搧' }}
-          </el-button>
-        </el-form-item>
-        <el-form-item label="鍗曚綅"
-                      prop="unit">
-          <el-input v-model="form.unit"
-                    :placeholder="form.productModelId ? '鏍规嵁閫夋嫨鐨勪骇鍝佽嚜鍔ㄥ甫鍑�' : '璇峰厛閫夋嫨浜у搧'"
-                    clearable
-                    :disabled="true" />
         </el-form-item>
         <el-form-item label="鏄惁璐ㄦ"
                       prop="isQuality">
@@ -288,6 +284,7 @@
     sortRouteItem,
   } from "@/api/productionManagement/productProcessRoute.js";
   import { processList } from "@/api/productionManagement/productionProcess.js";
+  import { queryList } from "@/api/productionManagement/productStructure.js";
   import { useRoute } from "vue-router";
   import { ElMessageBox, ElMessage } from "element-plus";
   import Sortable from "sortablejs";
@@ -313,6 +310,7 @@
     productName: "",
     model: "",
     bomNo: "",
+    dictLabel: "",
     bomId: null,
     description: "",
   });
@@ -322,6 +320,7 @@
   const showParamListDialog = ref(false);
   const currentProcess = ref(null);
   const paramList = ref([]);
+  const bomTableData = ref([]);
   let tableSortable = null;
   let cardSortable = null;
 
@@ -347,9 +346,6 @@
 
   const rules = {
     processId: [{ required: true, message: "璇烽�夋嫨宸ュ簭", trigger: "change" }],
-    productModelId: [
-      { required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" },
-    ],
   };
 
   // 鏍规嵁宸ュ簭ID鑾峰彇宸ュ簭鍚嶇О
@@ -401,9 +397,32 @@
       productName: route.query.productName || "",
       model: route.query.model || "",
       bomNo: route.query.bomNo || "",
+      dictLabel: route.query.dictLabel || "",
       bomId: route.query.bomId || null,
       description: route.query.description || "",
     };
+
+    // 濡傛灉鏈塨omId锛岃幏鍙朆OM鏁版嵁
+    if (routeInfo.value.bomId) {
+      queryList(routeInfo.value.bomId)
+        .then(res => {
+          if (res.data) {
+            bomTableData.value = [
+              {
+                bomNo: routeInfo.value.bomNo,
+                dictLabel: routeInfo.value.dictLabel,
+                productCode: "",
+                productName: routeInfo.value.productName,
+                model: routeInfo.value.model,
+                bomList: res.data,
+              },
+            ];
+          }
+        })
+        .catch(err => {
+          console.error("鑾峰彇BOM鏁版嵁澶辫触锛�", err);
+        });
+    }
   };
 
   // 鏂板
@@ -765,6 +784,8 @@
 <style scoped>
   .card-container {
     padding: 20px 0;
+    /* height: 350px; */
+    margin-bottom: 20px;
   }
 
   .cards-wrapper {
@@ -902,13 +923,13 @@
     opacity: 0.8;
   }
 
-  /* 琛ㄦ牸瑙嗗浘鏍峰紡 */
-  :deep(.el-table__row) {
+  /* 琛ㄦ牸瑙嗗浘鏍峰紡 - 浠呭簲鐢ㄤ簬椤圭洰鍒楄〃 */
+  :deep(.lims-table .el-table__row) {
     transition: background-color 0.2s;
     cursor: move;
   }
 
-  :deep(.el-table__row:hover) {
+  :deep(.lims-table .el-table__row:hover) {
     background-color: #f9fafc !important;
   }
 
@@ -957,7 +978,7 @@
 
   .route-info {
     display: grid;
-    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
+    grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
     gap: 16px;
     padding: 4px;
   }
diff --git a/src/views/productionManagement/productStructure/Detail/index.vue b/src/views/productionManagement/productStructure/Detail/index.vue
index 9cd0976..e26b502 100644
--- a/src/views/productionManagement/productStructure/Detail/index.vue
+++ b/src/views/productionManagement/productStructure/Detail/index.vue
@@ -141,12 +141,8 @@
       </el-table-column>
       <el-table-column label="BOM缂栧彿"
                        prop="bomNo" />
-      <el-table-column label="浜у搧缂栫爜"
-                       prop="productCode" />
-      <el-table-column label="浜у搧鍚嶇О"
-                       prop="productName" />
-      <el-table-column label="瑙勬牸鍨嬪彿"
-                       prop="model" />
+      <el-table-column label="浜у搧绫诲瀷"
+                       prop="dictLabel" />
     </el-table>
     <div v-if="dataValue.isEdit && dataValue.dataList.length == 0"
          style="text-align: center;border: 1px solid #e4e7ed;padding: 10px;transition: all 0.3s ease;cursor: pointer;"
@@ -206,11 +202,8 @@
 
   // 浠庤矾鐢卞弬鏁拌幏鍙栦骇鍝佷俊鎭�
   const routeBomNo = computed(() => route.query.bomNo || "");
-  const routeProductCode = computed(() => route.query.productCode || "");
-  const routeProductName = computed(() => route.query.productName || "");
-  const routeProductModelName = computed(
-    () => route.query.productModelName || ""
-  );
+  const routeDictLabel = computed(() => route.query.dictLabel || "");
+
   const routeOrderId = computed(() => route.query.orderId);
   const pageType = computed(() => route.query.type);
   const isOrderPage = computed(
@@ -230,9 +223,8 @@
 
   const tableData = reactive([
     {
-      productName: "",
-      model: "",
       bomNo: "",
+      dictLabel: "",
     },
   ]);
 
@@ -539,9 +531,8 @@
 
   onMounted(async () => {
     // 浠庤矾鐢卞弬鏁板洖鏄炬暟鎹�
-    tableData[0].productName = routeProductName.value as string;
-    tableData[0].model = routeProductModelName.value as string;
     tableData[0].bomNo = routeBomNo.value as string;
+    tableData[0].dictLabel = routeDictLabel.value as string;
 
     // 璁㈠崟鎯呭喌涓嬬鐢ㄧ紪杈�
     if (isOrderPage.value) {
diff --git a/src/views/productionManagement/productStructure/index.vue b/src/views/productionManagement/productStructure/index.vue
index 7032c09..2309dad 100644
--- a/src/views/productionManagement/productStructure/index.vue
+++ b/src/views/productionManagement/productStructure/index.vue
@@ -567,8 +567,7 @@
       query: {
         id: row.id,
         bomNo: row.bomNo || "",
-        productName: row.productName || "",
-        productModelName: row.productModelName || "",
+        dictLabel: row.dictLabel || "",
       },
     });
   };

--
Gitblit v1.9.3