From add86852b44af3dfb55c70c4d7b3ea9bb4fca227 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 15 四月 2026 17:41:20 +0800
Subject: [PATCH] 中兴实强 1.新增工艺路线的时候产品可以多选 2.绑定工艺路线时,可以删减工序并且每道工序可以多选报工人 3.报工列表展示报工人,非本订单报工人不可报工 其他

---
 src/views/productionManagement/processRoute/New.vue |  277 ++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 171 insertions(+), 106 deletions(-)

diff --git a/src/views/productionManagement/processRoute/New.vue b/src/views/productionManagement/processRoute/New.vue
index 856a2a4..9e876dd 100644
--- a/src/views/productionManagement/processRoute/New.vue
+++ b/src/views/productionManagement/processRoute/New.vue
@@ -1,54 +1,54 @@
 <template>
   <div>
     <el-dialog
-        v-model="isShow"
-        title="鏂板宸ヨ壓璺嚎"
-        width="400"
-        @close="closeModal"
+      v-model="isShow"
+      title="鏂板宸ヨ壓璺嚎"
+      width="800"
+      @close="closeModal"
     >
-      <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
+      <el-form ref="formRef" label-width="140px" :model="formState" label-position="top">
         <el-form-item
-            label="浜у搧澶х被锛�"
-            prop="productId"
-            :rules="[
-                {
-                required: true,
-                message: '璇烽�夋嫨浜у搧澶х被',
-              }
-            ]"
+          label="浜у搧鍚嶇О"
+          prop="selectedProducts"
+          :rules="[
+            {
+              required: true,
+              message: '璇烽�夋嫨浜у搧',
+              trigger: 'change',
+            },
+          ]"
         >
-          <el-tree-select
-              v-model="formState.productId"
-              placeholder="璇烽�夋嫨"
-              clearable
-              check-strictly
-              @change="getModels"
-              :data="productOptions"
-              :render-after-expand="false"
-              style="width: 100%"
-          />
+          <div class="product-picker">
+            <el-button type="primary" @click="showProductSelectDialog = true">
+              {{ formState.selectedProducts.length ? "閲嶆柊閫夋嫨浜у搧" : "閫夋嫨浜у搧" }}
+            </el-button>
+            <div v-if="formState.selectedProducts.length" class="product-tags">
+              <el-tag
+                v-for="product in formState.selectedProducts"
+                :key="product.id"
+                type="info"
+                effect="plain"
+                class="product-tag"
+              >
+                {{ product.productName }} / {{ product.model }}
+              </el-tag>
+            </div>
+          </div>
         </el-form-item>
 
-        <el-form-item
-            label="瑙勬牸鍨嬪彿锛�"
-            prop="productModelId"
-            :rules="[
-                {
-                required: true,
-                message: '璇烽�夋嫨瑙勬牸鍨嬪彿',
-              }
-            ]"
-        >
+        <el-form-item label="BOM" prop="bomId">
           <el-select
-              v-model="formState.productModelId"
-              placeholder="璇烽�夋嫨"
-              clearable
+            v-model="formState.bomId"
+            placeholder="璇烽�夋嫨BOM"
+            clearable
+            :disabled="bomOptions.length === 0"
+            style="width: 100%"
           >
             <el-option
-                v-for="item in productModelsOptions"
-                :key="item.id"
-                :label="item.model"
-                :value="item.id"
+              v-for="item in bomOptions"
+              :key="item.id"
+              :label="item.bomNo || `BOM-${item.id}`"
+              :value="item.id"
             />
           </el-select>
         </el-form-item>
@@ -57,6 +57,11 @@
           <el-input v-model="formState.description" type="textarea" />
         </el-form-item>
       </el-form>
+
+      <ProductSelectDialog
+        v-model="showProductSelectDialog"
+        @confirm="handleProductSelect"
+      />
       <template #footer>
         <div class="dialog-footer">
           <el-button type="primary" @click="handleSubmit">纭</el-button>
@@ -68,9 +73,10 @@
 </template>
 
 <script setup>
-import {ref, computed, getCurrentInstance, onMounted} from "vue";
-import {add} from "@/api/productionManagement/processRoute.js";
-import {modelList, productTreeList} from "@/api/basicData/product.js";
+import { computed, getCurrentInstance, ref } from "vue";
+import { add } from "@/api/productionManagement/processRoute.js";
+import { getByModelList } from "@/api/productionManagement/productBom.js";
+import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
 
 const props = defineProps({
   visible: {
@@ -79,13 +85,20 @@
   },
 });
 
-const emit = defineEmits(['update:visible', 'completed']);
+const emit = defineEmits(["update:visible", "completed"]);
 
-// 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
+const formRef = ref();
+const showProductSelectDialog = ref(false);
+const bomOptions = ref([]);
 const formState = ref({
   productId: undefined,
   productModelId: undefined,
-  description: '',
+  productModelIds: "",
+  productName: "",
+  productModelName: "",
+  selectedProducts: [],
+  bomId: undefined,
+  description: "",
 });
 
 const isShow = computed({
@@ -93,89 +106,141 @@
     return props.visible;
   },
   set(val) {
-    emit('update:visible', val);
+    emit("update:visible", val);
   },
 });
 
-const productModelsOptions = ref([])
-const productOptions = ref([])
+const { proxy } = getCurrentInstance();
 
-let { proxy } = getCurrentInstance()
+const resetForm = () => {
+  formState.value = {
+    productId: undefined,
+    productModelId: undefined,
+    productModelIds: "",
+    productName: "",
+    productModelName: "",
+    selectedProducts: [],
+    bomId: undefined,
+    description: "",
+  };
+  bomOptions.value = [];
+};
 
 const closeModal = () => {
+  resetForm();
   isShow.value = false;
 };
 
-const getProductOptions = () => {
-  productTreeList().then((res) => {
-    productOptions.value = convertIdToValue(res);
-  });
-};
-const getModels = (value) => {
-  formState.value.productId = undefined;
-  formState.value.productModelId = undefined;
-  productModelsOptions.value = [];
+const loadBomList = async (productModelIds) => {
+  if (!productModelIds?.length) {
+    bomOptions.value = [];
+    return;
+  }
 
-  if (value) {
-    formState.value.productId = findNodeById(productOptions.value, value) || undefined;
-    modelList({ id: value }).then((res) => {
-      productModelsOptions.value = res;
-    });
+  try {
+    const res = await getByModelList(productModelIds);
+    if (Array.isArray(res)) {
+      bomOptions.value = res;
+      return;
+    }
+    if (res && res.data) {
+      bomOptions.value = Array.isArray(res.data) ? res.data : [res.data];
+      return;
+    }
+    bomOptions.value = res && typeof res === "object" ? [res] : [];
+  } catch (error) {
+    bomOptions.value = [];
   }
 };
 
-const findNodeById = (nodes, productId) => {
-  for (let i = 0; i < nodes.length; i++) {
-    if (nodes[i].value === productId) {
-      return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣鐨刲abel
-    }
-    if (nodes[i].children && nodes[i].children.length > 0) {
-      const foundNode = findNodeById(nodes[i].children, productId);
-      if (foundNode) {
-        return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝鐩存帴杩斿洖锛堝凡缁忔槸label瀛楃涓诧級
-      }
-    }
+const handleProductSelect = async (products) => {
+  if (!products?.length) {
+    return;
   }
-  return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+
+  formState.value.selectedProducts = products;
+  formState.value.productModelIds = products.map((product) => product.id).join(",");
+  formState.value.bomId = undefined;
+
+  if (products.length === 1) {
+    const product = products[0];
+    formState.value.productId = product.productId;
+    formState.value.productModelId = product.id;
+    formState.value.productName = product.productName;
+    formState.value.productModelName = product.model;
+    await loadBomList([product.id]);
+  } else {
+    formState.value.productId = undefined;
+    formState.value.productModelId = undefined;
+    formState.value.productName = "";
+    formState.value.productModelName = "";
+    await loadBomList(products.map((product) => product.id));
+  }
+
+  showProductSelectDialog.value = false;
+  formRef.value?.validateField("selectedProducts");
 };
-
-function convertIdToValue(data) {
-  return data.map((item) => {
-    const { id, children, ...rest } = item;
-    const newItem = {
-      ...rest,
-      value: id, // 灏� id 鏀逛负 value
-    };
-    if (children && children.length > 0) {
-      newItem.children = convertIdToValue(children);
-    }
-
-    return newItem;
-  });
-}
 
 const handleSubmit = () => {
-  proxy.$refs["formRef"].validate(valid => {
-    if (valid) {
-      add(formState.value).then(res => {
-        // 鍏抽棴妯℃�佹
-        isShow.value = false;
-        // 鍛婄煡鐖剁粍浠跺凡瀹屾垚
-        emit('completed');
-        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-      })
+  formRef.value.validate((valid) => {
+    if (!valid) {
+      return;
     }
-  })
-};
+    if (!formState.value.selectedProducts.length) {
+      proxy.$modal.msgError("璇烽�夋嫨浜у搧");
+      return;
+    }
 
+    add({
+      productId: formState.value.selectedProducts.length === 1
+        ? formState.value.selectedProducts[0].productId
+        : undefined,
+      productModelId: formState.value.selectedProducts.length === 1
+        ? formState.value.selectedProducts[0].id
+        : undefined,
+      productModelIds: formState.value.productModelIds,
+      productName: formState.value.selectedProducts.length === 1
+        ? formState.value.selectedProducts[0].productName
+        : undefined,
+      productModelName: formState.value.selectedProducts.length === 1
+        ? formState.value.selectedProducts[0].model
+        : undefined,
+      bomId: formState.value.bomId,
+      description: formState.value.description,
+    })
+      .then(() => {
+        isShow.value = false;
+        emit("completed");
+        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+        resetForm();
+      })
+      .catch(() => {});
+  });
+};
 
 defineExpose({
   closeModal,
   handleSubmit,
   isShow,
 });
-
-onMounted(() => {
-  getProductOptions()
-})
 </script>
+
+<style scoped>
+.product-picker {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+  align-items: flex-start;
+}
+
+.product-tags {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+
+.product-tag {
+  max-width: 220px;
+}
+
+</style>

--
Gitblit v1.9.3