From 3da0bb27192b279add20dcfcd9899c17c84b9785 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 23 七月 2026 15:28:06 +0800
Subject: [PATCH] 湟水峡 1.销售订单可绑定多条生产订单 2.生产订单页面展示销售订单优化

---
 src/views/productionManagement/productionOrder/index.vue |   37 ++++++++++--
 src/api/productionManagement/productionOrder.js          |    9 +++
 src/views/salesManagement/salesLedger/index.vue          |   75 +++++++++++++++++++++++++
 3 files changed, 114 insertions(+), 7 deletions(-)

diff --git a/src/api/productionManagement/productionOrder.js b/src/api/productionManagement/productionOrder.js
index b8468eb..1047fb3 100644
--- a/src/api/productionManagement/productionOrder.js
+++ b/src/api/productionManagement/productionOrder.js
@@ -18,6 +18,15 @@
   });
 }
 
+// 鏍规嵁浜у搧鍨嬪彿ID鏌ヨ鐢熶骇璁㈠崟鍒楄〃
+export function listByProductModelId(data) {
+  return request({
+    url: "/productOrder/listByProductModelId",
+    method: "post",
+    data,
+  });
+}
+
 // 鐢熶骇璁㈠崟-鎸変骇鍝佸瀷鍙锋煡璇㈠彲鐢ㄥ伐鑹鸿矾绾垮垪琛�
 export function listProcessRoute(query) {
   return request({
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 4fb07f1..1932e2b 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -71,6 +71,20 @@
             :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''"
           />
         </template>
+        <template #salesContractNo="{ row }">
+          <template v-if="row.salesContractNos && row.salesContractNos.length > 0">
+            <el-tag v-for="(no, idx) in row.salesContractNos" :key="idx" size="small" style="margin: 2px;">{{ no }}</el-tag>
+          </template>
+          <span v-else-if="row.salesContractNo">{{ row.salesContractNo }}</span>
+          <span v-else>-</span>
+        </template>
+        <template #customerName="{ row }">
+          <template v-if="row.customerNames && row.customerNames.length > 0">
+            <el-tag v-for="(name, idx) in row.customerNames" :key="idx" size="small" style="margin: 2px;">{{ name }}</el-tag>
+          </template>
+          <span v-else-if="row.customerName">{{ row.customerName }}</span>
+          <span v-else>-</span>
+        </template>
       </PIMTable>
     </div>
     <el-dialog v-model="bindRouteDialogVisible"
@@ -148,11 +162,15 @@
       label: "閿�鍞悎鍚屽彿",
       prop: "salesContractNo",
       width: '150px',
+      dataType: "slot",
+      slot: "salesContractNo",
     },
     {
       label: "瀹㈡埛鍚嶇О",
       prop: "customerName",
       width: '200px',
+      dataType: "slot",
+      slot: "customerName",
     },
     {
       label: "浜у搧鍚嶇О",
@@ -196,12 +214,12 @@
       formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
       width: 120,
     },
-    {
-      label: "浜や粯鏃ユ湡",
-      prop: "deliveryDate",
-      formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
-      width: 120,
-    },
+    // {
+    //   label: "浜や粯鏃ユ湡",
+    //   prop: "deliveryDate",
+    //   formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
+    //   width: 120,
+    // },
     {
       dataType: "action",
       label: "鎿嶄綔",
@@ -400,7 +418,12 @@
     productOrderListPage(params)
       .then(res => {
         tableLoading.value = false;
-        tableData.value = res.data.records;
+        const records = res.data.records || [];
+        records.forEach(row => {
+          row.salesContractNos = row.salesContractNo ? row.salesContractNo.split(',').filter(Boolean) : [];
+          row.customerNames = row.customerName ? row.customerName.split(',').filter(Boolean) : [];
+        });
+        tableData.value = records;
         page.total = res.data.total;
       })
       .catch(() => {
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 582fdf1..565a048 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -123,6 +123,14 @@
         <el-table-column label="褰曞叆浜�" prop="entryPersonName" width="100" show-overflow-tooltip />
         <el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" width="120" show-overflow-tooltip />
         <el-table-column label="绛捐鏃ユ湡" prop="executionDate" width="120" show-overflow-tooltip />
+        <el-table-column label="鐢熶骇璁㈠崟鍙�" min-width="180" show-overflow-tooltip>
+          <template #default="scope">
+            <template v-if="scope.row.productionOrders && scope.row.productionOrders.length > 0">
+              <el-tag v-for="order in scope.row.productionOrders" :key="order.id" size="small" style="margin: 2px;">{{ order.npsNo }}</el-tag>
+            </template>
+            <span v-else>-</span>
+          </template>
+        </el-table-column>
         <el-table-column fixed="right" label="鎿嶄綔" min-width="140" align="center">
           <template #default="scope">
             <el-button link type="primary" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit || scope.row.hasProductionRecord">缂栬緫</el-button>
@@ -208,6 +216,30 @@
           <el-col :span="12">
             <el-form-item label="浠樻鏂瑰紡">
               <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鐢熶骇璁㈠崟锛�">
+              <el-select
+                v-model="form.productionOrderIds"
+                multiple
+                filterable
+                remote
+                :remote-method="getProductOrderOptions"
+                :loading="productOrderLoading"
+                placeholder="璇烽�夋嫨鐢熶骇璁㈠崟"
+                clearable
+                collapse-tags
+                collapse-tags-tooltip
+                :disabled="operationType === 'view'"
+              >
+                <el-option
+                  v-for="item in productOrderOptions"
+                  :key="item.id"
+                  :label="item.npsNo + (item.productCategory ? ' - ' + item.productCategory : '') + (item.specificationModel ? ' - ' + item.specificationModel : '')"
+                  :value="item.id"
+                />
+              </el-select>
             </el-form-item>
           </el-col>
         </el-row>
@@ -631,6 +663,7 @@
 } from "@/api/salesManagement/salesLedger.js";
 import { getQuotationDetail } from "@/api/salesManagement/salesQuotation.js";
 import { modelList, productTreeList } from "@/api/basicData/product.js";
+import { productOrderListPage, listByProductModelId } from "@/api/productionManagement/productionOrder.js";
 import useFormData from "@/hooks/useFormData.js";
 import dayjs from "dayjs";
 import { getCurrentDate } from "@/utils/index.js";
@@ -646,6 +679,8 @@
 const customerOption = ref([]);
 const productOptions = ref([]);
 const modelOptions = ref([]);
+const productOrderOptions = ref([]);
+const productOrderLoading = ref(false);
 const tableLoading = ref(false);
 const page = reactive({
   current: 1,
@@ -686,6 +721,7 @@
     productData: [],
     executionDate: "",
     paymentMethod: "",
+    productionOrderIds: [],
   },
   rules: {
     salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
@@ -830,6 +866,24 @@
     productOptions.value = convertIdToValue(list);
     return productOptions.value;
   });
+};
+// 鑾峰彇鐢熶骇璁㈠崟鍒楄〃
+const getProductOrderOptions = (query) => {
+  productOrderLoading.value = true;
+  const productModelIds = productData.value
+    .map(item => item.productModelId)
+    .filter(id => id != null);
+  if (productModelIds.length > 0) {
+    listByProductModelId(productModelIds)
+      .then((res) => {
+        productOrderOptions.value = res?.data?.records || res?.data || res || [];
+      })
+      .finally(() => {
+        productOrderLoading.value = false;
+      });
+    return;
+  }
+  productOrderLoading.value = false;
 };
 const formattedNumber = (row, column, cellValue) => {
   return parseFloat(cellValue).toFixed(2);
@@ -1000,6 +1054,9 @@
     // 鏂板鏃堕噸缃鎵逛汉鑺傜偣
     approverNodes.value = [{ id: 1, userId: null }];
     nextApproverId = 2;
+    form.value.productionOrderIds = [];
+    // 鏂板鏃剁洿鎺ュ姞杞界敓浜ц鍗曞垪琛�
+    getProductOrderOptions();
   } else {
     currentId.value = row.id;
     getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
@@ -1007,6 +1064,23 @@
       form.value.entryPerson = Number(res.entryPerson);
       productData.value = form.value.productData;
       fileList.value = form.value.salesLedgerFiles;
+      // 鍥炴樉鐢熶骇璁㈠崟
+      if (res.productionOrders && res.productionOrders.length > 0) {
+        form.value.productionOrderIds = res.productionOrders.map(order => order.id);
+        productOrderOptions.value = res.productionOrders;
+      } else if (res.productOrderIds) {
+        if (Array.isArray(res.productOrderIds)) {
+          form.value.productionOrderIds = res.productOrderIds.map(id => Number(id));
+        } else if (typeof res.productOrderIds === "string") {
+          form.value.productionOrderIds = res.productOrderIds.split(",").filter(id => id).map(id => Number(id));
+        } else {
+          form.value.productionOrderIds = [];
+        }
+      } else {
+        form.value.productionOrderIds = [];
+      }
+      // 缂栬緫鏃舵牴鎹骇鍝佸瀷鍙稩D鍔犺浇鐢熶骇璁㈠崟鍒楄〃
+      getProductOrderOptions();
       // 鍥炴樉瀹℃壒浜鸿妭鐐�
       if (res.approveUserIds) {
         const userIds = res.approveUserIds.split(",").filter(id => id);
@@ -1204,6 +1278,7 @@
 const closeDia = () => {
   proxy.resetForm("formRef");
   dialogFormVisible.value = false;
+  productOrderOptions.value = [];
   // 閲嶇疆瀹℃壒浜鸿妭鐐�
   approverNodes.value = [{ id: 1, userId: null }];
   nextApproverId = 2;

--
Gitblit v1.9.3