From 04d6024553ac73e67148ce578cb01b541eebd02a Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期一, 18 五月 2026 16:37:56 +0800
Subject: [PATCH] Merge branch 'dev_NEW_pro' into dev-new_pro_OA

---
 src/views/productionPlan/productionPlan/index.vue |  296 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 156 insertions(+), 140 deletions(-)

diff --git a/src/views/productionPlan/productionPlan/index.vue b/src/views/productionPlan/productionPlan/index.vue
index 182a351..01a513b 100644
--- a/src/views/productionPlan/productionPlan/index.vue
+++ b/src/views/productionPlan/productionPlan/index.vue
@@ -2,16 +2,27 @@
   <div class="app-container">
     <div class="search_form">
       <el-form :model="searchForm"
+               ref="queryRef"
                :inline="true">
         <!-- 绠�鍖栫増鎼滅储鏉′欢 -->
-        <el-form-item label="涓荤敓浜ц鍒掑彿:">
+        <el-form-item label="涓荤敓浜ц鍒掑彿:"
+                      prop="mpsNo">
           <el-input v-model="searchForm.mpsNo"
                     placeholder="璇疯緭鍏�"
                     clearable
                     style="width: 160px;"
                     @keyup.enter="handleQuery" />
         </el-form-item>
-        <el-form-item label="闇�姹傛棩鏈熻寖鍥�:">
+        <el-form-item label="閿�鍞悎鍚屽彿:"
+                      prop="salesContractNo">
+          <el-input v-model="searchForm.salesContractNo"
+                    placeholder="璇疯緭鍏�"
+                    clearable
+                    style="width: 160px;"
+                    @keyup.enter="handleQuery" />
+        </el-form-item>
+        <el-form-item label="闇�姹傛棩鏈熻寖鍥�:"
+                      prop="dateRange">
           <el-date-picker v-model="searchForm.dateRange"
                           type="daterange"
                           range-separator="鑷�"
@@ -21,7 +32,8 @@
                           style="width: 240px;"
                           @change="handleQuery" />
         </el-form-item>
-        <el-form-item label="涓嬪彂鐘舵��:">
+        <el-form-item label="涓嬪彂鐘舵��:"
+                      prop="status">
           <el-select v-model="searchForm.status"
                      placeholder="璇烽�夋嫨鐘舵��"
                      clearable
@@ -36,36 +48,22 @@
           </el-select>
         </el-form-item>
         <!-- 灞曞紑鐗堟悳绱㈡潯浠� -->
-        <template v-if="searchFormExpanded">
-          <el-form-item label="浜у搧鍚嶇О:">
-            <el-input v-model="searchForm.productName"
-                      placeholder="璇疯緭鍏�"
-                      clearable
-                      style="width: 160px;"
-                      @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item label="浜у搧瑙勬牸:">
-            <el-input v-model="searchForm.model"
-                      placeholder="璇疯緭鍏�"
-                      clearable
-                      style="width: 160px;"
-                      @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item label="鐗╂枡缂栫爜:">
-            <el-input v-model="searchForm.materialCode"
-                      placeholder="璇疯緭鍏�"
-                      clearable
-                      style="width: 160px;"
-                      @keyup.enter="handleQuery" />
-          </el-form-item>
-          <el-form-item label="鐢宠鍗曠紪鍙�:">
-            <el-input v-model="searchForm.applyNo"
-                      placeholder="璇疯緭鍏�"
-                      clearable
-                      style="width: 160px;"
-                      @keyup.enter="handleQuery" />
-          </el-form-item>
-        </template>
+        <el-form-item label="浜у搧鍚嶇О:"
+                      prop="productName">
+          <el-input v-model="searchForm.productName"
+                    placeholder="璇疯緭鍏�"
+                    clearable
+                    style="width: 160px;"
+                    @keyup.enter="handleQuery" />
+        </el-form-item>
+        <el-form-item label="浜у搧瑙勬牸:"
+                      prop="model">
+          <el-input v-model="searchForm.model"
+                    placeholder="璇疯緭鍏�"
+                    clearable
+                    style="width: 160px;"
+                    @keyup.enter="handleQuery" />
+        </el-form-item>
         <el-form-item>
           <el-button type="primary"
                      @click="handleQuery">鎼滅储</el-button>
@@ -74,6 +72,8 @@
           <el-button type="primary"
                      @click="handleAdd">鏂板</el-button>
           <el-button type="warning"
+                     @click="handleMerge">鍚堝苟涓嬪彂</el-button>
+          <el-button type="warning"
                      @click="handleImport">瀵煎叆</el-button>
           <el-button type="warning"
                      @click="handleExport">瀵煎嚭</el-button>
@@ -81,16 +81,6 @@
       </el-form>
       <div>
       </div>
-    </div>
-    <div class="search-header">
-      <el-button type="text"
-                 @click="toggleSearchForm">
-        <el-icon>
-          <ArrowUp v-if="searchFormExpanded" />
-          <ArrowDown v-else />
-        </el-icon>
-        {{ searchFormExpanded ? '鏀惰捣鎼滅储鏉′欢' : '灞曞紑鎼滅储鏉′欢' }}
-      </el-button>
     </div>
     <div class="table_list">
       <PIMTable rowKey="id"
@@ -106,6 +96,13 @@
         <template #qtyRequired="{ row }">
           {{ row.qtyRequired || '-' }}<span style="color:rgba(12, 46, 40, 0.76)"> {{ row.unit || '鏂�' }}</span>
         </template>
+        <template #salesContractNo="{ row }">
+          <el-button type="primary"
+                     text
+                     link
+                     @click="showDetail(row)">{{ row.salesContractNo }}
+          </el-button>
+        </template>
       </PIMTable>
     </div>
     <!-- 鍚堝苟涓嬪彂寮圭獥 -->
@@ -117,23 +114,16 @@
                label-width="120px">
         <el-row :gutter="20">
           <el-col :span="10">
-            <el-form-item label="鐗╂枡缂栫爜">
-              <div class="info-display">{{ mergeForm.materialCode || '-' }}</div>
-            </el-form-item>
-          </el-col>
-          <el-col :span="10">
             <el-form-item label="浜у搧鍚嶇О">
               <el-tag class="info-display">{{ mergeForm.productName || '-' }}</el-tag>
             </el-form-item>
           </el-col>
         </el-row>
         <el-row :gutter="20">
-          <el-col :span="10">
+          <el-col>
             <el-form-item label="浜у搧瑙勬牸">
               <div class="info-display">{{ mergeForm.model || '-' }}</div>
             </el-form-item>
-          </el-col>
-          <el-col :span="10">
           </el-col>
         </el-row>
         <el-form-item label="璁″垝瀹屾垚鏃堕棿">
@@ -142,7 +132,7 @@
                           value-format="YYYY-MM-DD"
                           style="width: 100%" />
         </el-form-item>
-        <el-form-item label="鐢熶骇鏂规暟">
+        <el-form-item label="鐢熶骇鏁伴噺">
           <el-input-number v-model="mergeForm.totalAssignedQuantity"
                            :min="0"
                            :max="sumAssignedQuantity"
@@ -152,9 +142,9 @@
       </el-form>
       <template #footer>
         <span class="dialog-footer">
-          <el-button @click="isShowNewModal = false">鍙栨秷</el-button>
           <el-button type="primary"
                      @click="handleMergeSubmit">纭畾涓嬪彂</el-button>
+          <el-button @click="isShowNewModal = false">鍙栨秷</el-button>
         </span>
       </template>
     </el-dialog>
@@ -182,16 +172,12 @@
         <el-form-item label="涓荤敓浜ц鍒掑彿"
                       prop="mpsNo">
           <el-input v-model="form.mpsNo"
-                    placeholder="璇疯緭鍏ヤ富鐢熶骇璁″垝鍙�" />
-        </el-form-item>
-        <el-form-item label="鐢宠鍗曠紪鍙�"
-                      prop="applyNo">
-          <el-input v-model="form.applyNo"
-                    placeholder="璇疯緭鍏ョ敵璇峰崟缂栧彿" />
+                    disabled
+                    placeholder="鏂板鍚庤嚜鍔ㄧ敓鎴�" />
         </el-form-item>
         <el-form-item label="浜у搧鍚嶇О"
-                      prop="productMaterialId">
-          <el-tree-select v-model="form.productMaterialId"
+                      prop="productId">
+          <el-tree-select v-model="form.productId"
                           placeholder="璇烽�夋嫨"
                           clearable
                           :data="productOptions"
@@ -250,9 +236,9 @@
       </el-form>
       <template #footer>
         <span class="dialog-footer">
-          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
           <el-button type="primary"
                      @click="handleSubmit">纭畾</el-button>
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
         </span>
       </template>
     </el-dialog>
@@ -279,6 +265,8 @@
     productionPlanAdd,
     productionPlanUpdate,
     productionPlanDelete,
+    productionPlanCombine,
+    exportProductionPlan,
   } from "@/api/productionPlan/productionPlan.js";
   import { productTreeList, modelListPage } from "@/api/basicData/product.js";
   import PIMTable from "./components/PIMTable.vue";
@@ -292,15 +280,10 @@
     return Promise.resolve({ code: 200, msg: "鍚屾鎴愬姛" });
   };
 
-  const exportProductionPlan = () => {
-    console.log("Mock exportProductionPlan called");
-    return Promise.resolve();
-  };
-
-  const productionPlanCombine = payload => {
-    console.log("Mock productionPlanCombine called with:", payload);
-    return Promise.resolve({ code: 200, msg: "鍚堝苟涓嬪彂鎴愬姛" });
-  };
+  // const productionPlanCombine = payload => {
+  //   console.log("Mock productionPlanCombine called with:", payload);
+  //   return Promise.resolve({ code: 200, msg: "鍚堝苟涓嬪彂鎴愬姛" });
+  // };
 
   const tableColumn = ref([
     {
@@ -309,15 +292,18 @@
       width: "150px",
     },
     {
-      label: "鐢宠鍗曠紪鍙�",
-      prop: "applyNo",
+      label: "鏉ユ簮",
+      prop: "source",
       width: "150px",
+      dataType: "tag",
+      formatType: params => {
+        return params == "閿�鍞�" ? "primary" : "info";
+      },
+      formatData: params => {
+        return params == "閿�鍞�" ? "閿�鍞�" : "鍐呴儴";
+      },
     },
-    {
-      label: "鐗╂枡缂栫爜",
-      prop: "materialCode",
-      width: "150px",
-    },
+
     {
       label: "浜у搧鍚嶇О",
       prop: "productName",
@@ -372,7 +358,7 @@
     },
     {
       label: "宸蹭笅鍙戞暟閲�",
-      prop: "assignedQuantity",
+      prop: "quantityIssued",
       width: "120px",
       className: "spec-cell",
       // formatData: (cell, row) => (cell ? `${cell}${row.unit || "鏂�"}` : 0),
@@ -392,6 +378,23 @@
       formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
     },
     {
+      label: "閿�鍞悎鍚屽彿",
+      prop: "salesContractNo",
+      width: "200px",
+      dataType: "slot",
+      slot: "salesContractNo",
+    },
+    {
+      label: "瀹㈡埛鍚嶇О",
+      prop: "customerName",
+      width: "150px",
+    },
+    {
+      label: "椤圭洰鍚嶇О",
+      prop: "projectName",
+      width: "150px",
+    },
+    {
       label: "澶囨敞",
       width: "150px",
       prop: "remark",
@@ -401,17 +404,36 @@
       label: "鎿嶄綔",
       align: "center",
       fixed: "right",
-      width: 150,
+      width: 250,
       operation: [
         {
           name: "缂栬緫",
           type: "primary",
           link: true,
           showHide: row => {
-            return row.status == 0;
+            return row.status == 0 && row.source != "閿�鍞�";
           },
           clickFun: row => {
             handleEdit(row);
+          },
+        },
+        {
+          name: "涓嬪彂",
+          type: "text",
+          showHide: row => {
+            return row.status != 2;
+          },
+          clickFun: row => {
+            mergeForm.productName = row.productName || "";
+            mergeForm.model = row.model || "";
+            mergeForm.totalAssignedQuantity =
+              Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
+            mergeForm.planCompleteTime = row.requiredDate || "";
+            mergeForm.productId = row.productId || "";
+            mergeForm.ids = [row.id];
+            sumAssignedQuantity.value =
+              Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
+            isShowNewModal.value = true;
           },
         },
         {
@@ -446,12 +468,11 @@
   const isShowNewModal = ref(false);
   // 鍚堝苟涓嬪彂琛ㄥ崟鏁版嵁
   const mergeForm = reactive({
-    materialCode: "",
     productName: "",
     model: "",
     totalAssignedQuantity: 0,
     planCompleteTime: "",
-    productMaterialId: "",
+    productId: "",
   });
 
   // 瀵煎叆鐩稿叧
@@ -468,16 +489,15 @@
   const operationType = ref("add"); // add | edit
   const productOptions = ref([]);
   const specificationOptions = ref([]);
+  const queryRef = ref(null);
   const formRef = ref(null);
   const form = reactive({
     id: undefined,
     mpsNo: "",
-    applyNo: "",
-    productMaterialId: undefined,
+    productId: undefined,
     productModelId: undefined,
     productName: "",
     model: "",
-    materialCode: "",
     qtyRequired: 0,
     unit: "鏂�",
     requiredDate: "",
@@ -485,11 +505,7 @@
     remark: "",
   });
   const rules = reactive({
-    mpsNo: [{ required: true, message: "璇疯緭鍏ヤ富鐢熶骇璁″垝鍙�", trigger: "blur" }],
-    applyNo: [{ required: true, message: "璇疯緭鍏ョ敵璇峰崟缂栧彿", trigger: "blur" }],
-    productMaterialId: [
-      { required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" },
-    ],
+    productId: [{ required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" }],
     productModelId: [
       { required: true, message: "璇烽�夋嫨浜у搧瑙勬牸", trigger: "change" },
     ],
@@ -506,7 +522,6 @@
       path: "/productionPlan/trackProgress",
       query: {
         id: row.id,
-        applyNo: row.applyNo,
         productName: row.productName,
         model: row.model,
       },
@@ -539,7 +554,6 @@
   const handleProductChange = value => {
     form.productModelId = undefined;
     form.model = undefined;
-    form.materialCode = undefined;
     // 鏌ユ壘閫変腑鐨勪骇鍝佸悕绉�
     const findProductName = (options, val) => {
       for (const option of options) {
@@ -569,14 +583,12 @@
   };
 
   const handleChangeSpecification = value => {
-    form.materialCode = undefined;
     form.model = undefined;
     form.unit = "";
     const selectedModel = specificationOptions.value.find(
       item => item.id === value
     );
     if (selectedModel) {
-      form.materialCode = selectedModel.materialCode;
       form.model = selectedModel.model;
       form.unit = selectedModel.unit || "鏂�";
     }
@@ -585,10 +597,10 @@
   const data = reactive({
     searchForm: {
       mpsNo: "",
+      salesContractNo: "",
       productName: "",
       model: "",
-      materialCode: "",
-      applyNo: "",
+      status: "",
       dateRange: [],
     },
     searchFormExpanded: false,
@@ -609,12 +621,15 @@
 
   /** 閲嶇疆鎸夐挳鎿嶄綔 */
   const handleReset = () => {
+    if (proxy.resetForm) {
+      proxy.resetForm("queryRef");
+    }
     Object.assign(searchForm.value, {
       mpsNo: "",
+      salesContractNo: "",
       productName: "",
       model: "",
-      materialCode: "",
-      applyNo: "",
+      status: "",
       dateRange: [],
     });
     page.current = 1;
@@ -631,16 +646,18 @@
 
     // 閬嶅巻琛ㄦ牸鏁版嵁锛屾寜浜у搧绫诲埆姹囨��
     tableData.value.forEach(row => {
-      const category = row.materialCode;
+      const category = row.productName || "鏈煡浜у搧";
       if (!summary[category]) {
         summary[category] = {
           materialCode: category,
           totalAssignedQuantity: 0,
         };
       }
-      summary[category].totalAssignedQuantity += (
-        Number(row.qtyRequired) - Number(row.assignedQuantity)
-      ).toFixed(4);
+      summary[category].totalAssignedQuantity += Number(
+        (Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0)).toFixed(
+          4
+        )
+      );
     });
 
     // 杞崲涓烘暟缁勬牸寮�
@@ -651,8 +668,10 @@
     tableLoading.value = true;
     // 鏋勯�犳悳绱㈠弬鏁�
     const params = { ...searchForm.value, ...page };
-    params.requiredDateStart = params.dateRange ? params.dateRange[0] : "";
-    params.requiredDateEnd = params.dateRange ? params.dateRange[1] : "";
+    params.requiredDateStart =
+      params.dateRange && params.dateRange.length > 0 ? params.dateRange[0] : "";
+    params.requiredDateEnd =
+      params.dateRange && params.dateRange.length > 1 ? params.dateRange[1] : "";
     delete params.dateRange;
     productionPlanListPage(params)
       .then(res => {
@@ -667,35 +686,39 @@
       });
   };
 
-  // 閫変腑鐨勫簭鍒楀彿
-  const selectedserialNo = ref("");
+  // 閫変腑鐨勪骇鍝佽鏍糏D
+  const selectedProductModelId = ref("");
 
   // 琛ㄦ牸閫夋嫨鏁版嵁
   const handleSelectionChange = selection => {
     selectedRows.value = selection;
-    // 濡傛灉鏈夐�変腑鐨勮锛岃褰曠涓�涓�変腑琛岀殑搴忓垪鍙�
+    // 濡傛灉鏈夐�変腑鐨勮锛岃褰曠涓�涓�変腑琛岀殑浜у搧瑙勬牸ID
     if (selection.length > 0) {
-      selectedserialNo.value = selection[0].materialCode;
+      selectedProductModelId.value = selection[0].productModelId;
     } else {
-      // 濡傛灉娌℃湁閫変腑鐨勮锛屾竻绌哄簭鍒楀彿
-      selectedserialNo.value = "";
+      // 濡傛灉娌℃湁閫変腑鐨勮锛屾竻绌轰骇鍝佽鏍糏D
+      selectedProductModelId.value = "";
     }
   };
 
   // 鍒ゆ柇琛屾槸鍚﹀彲閫夋嫨
   const isSelectable = row => {
+    // 濡傛灉鏄凡涓嬪彂鐘舵�侊紝绂佹鍕鹃��
+    if (row.status == 2) {
+      return false;
+    }
     // 璁$畻鍓╀綑鏁伴噺
-    const remainingQty = (row.qtyRequired || 0) - (row.assignedQuantity || 0);
+    const remainingQty = (row.qtyRequired || 0) - (row.quantityIssued || 0);
     // 濡傛灉鍓╀綑鏁伴噺灏忎簬绛変簬0锛岀姝㈤�夋嫨
     if (remainingQty <= 0) {
       return false;
     }
     // 濡傛灉娌℃湁閫変腑鐨勮锛屾墍鏈夎閮藉彲閫夋嫨
-    if (!selectedserialNo.value) {
+    if (!selectedProductModelId.value) {
       return true;
     }
-    // 濡傛灉鏈夐�変腑鐨勮锛屽彧鏈夊簭鍒楀彿鐩稿悓鐨勮鎵嶅彲閫夋嫨
-    return row.materialCode === selectedserialNo.value;
+    // 濡傛灉鏈夐�変腑鐨勮锛屽彧鏈変骇鍝佽鏍糏D鐩稿悓鐨勮鎵嶅彲閫夋嫨
+    return row.productModelId === selectedProductModelId.value;
   };
   // 鎷夊彇鏁版嵁鎸夐挳鎿嶄綔
   const loadProdDataLoading = ref(false);
@@ -711,47 +734,43 @@
     const firstRow = selectedRows.value[0];
     const productName = firstRow.productName || "";
 
-    // 璁$畻鎬诲埗閫犳暟閲�
+    // 璁$畻鎬诲埗閫犳暟閲� (榛樿qtyRequired鐨勫拰)
     const totalAssignedQuantity = selectedRows.value.reduce((sum, row) => {
-      return (
-        sum +
-        (row.qtyRequired == null
-          ? 0
-          : Number(
-              Number(row.qtyRequired) - Number(row.assignedQuantity).toFixed(4)
-            ))
-      );
+      return sum + Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
     }, 0);
     sumAssignedQuantity.value = totalAssignedQuantity;
     console.log(totalAssignedQuantity);
     // 璁剧疆琛ㄥ崟鏁版嵁
-    mergeForm.materialCode = selectedserialNo.value;
     mergeForm.productName = productName;
     mergeForm.model = firstRow.model || "";
     mergeForm.totalAssignedQuantity = totalAssignedQuantity;
-    mergeForm.planCompleteTime = firstRow.planCompleteTime || "";
-    mergeForm.productMaterialId = firstRow.productMaterialId || "";
+    mergeForm.planCompleteTime = firstRow.requiredDate || "";
+    mergeForm.productId = firstRow.productId || "";
     mergeForm.ids = selectedRows.value.map(row => row.id);
 
     // 鎵撳紑寮圭獥
     isShowNewModal.value = true;
   };
+  const showDetail = row => {
+    router.push({
+      path: "/salesManagement/salesLedger",
+      query: {
+        salesContractNo: row.salesContractNo,
+      },
+    });
+  };
 
   // 澶勭悊鍚堝苟涓嬪彂鎻愪氦
   const handleMergeSubmit = () => {
     if (mergeForm.totalAssignedQuantity === 0) {
-      ElMessage.warning("璇疯緭鍏ョ敓浜ф柟鏁�");
+      ElMessage.warning("璇疯緭鍏ョ敓浜ф暟閲�");
       return;
     }
     console.log(sumAssignedQuantity.value, "sumAssignedQuantity");
-    // 璁$畻褰撳墠閫変腑琛岀殑鎬绘暟閲�
-    const totalVolume = selectedRows.value.reduce((sum, row) => {
-      return sum + (Number(row.qtyRequired) - Number(row.assignedQuantity) || 0);
-    }, 0);
 
     // 楠岃瘉totalAssignedQuantity涓嶈兘澶т簬鎬绘柟鏁�
     if (mergeForm.totalAssignedQuantity > sumAssignedQuantity.value) {
-      ElMessage.error("鐢熶骇鏂规暟涓嶈兘澶т簬褰撳墠璁$畻鐨勬�诲��");
+      ElMessage.error("鐢熶骇鏁伴噺涓嶈兘澶т簬褰撳墠璁$畻鐨勬�诲��");
       return;
     }
 
@@ -861,12 +880,10 @@
     Object.assign(form, {
       id: undefined,
       mpsNo: "",
-      applyNo: "",
       productName: "",
-      productMaterialId: undefined,
+      productId: undefined,
       productModelId: undefined,
       model: "",
-      materialCode: "",
       qtyRequired: 0,
       unit: "鏂�",
       requiredDate: "",
@@ -883,12 +900,10 @@
     Object.assign(form, {
       id: row.id,
       mpsNo: row.mpsNo || "",
-      applyNo: row.applyNo || "",
       productName: row.productName || "",
-      productMaterialId: row.productMaterialId || undefined,
+      productId: row.productId || undefined,
       productModelId: row.productModelId || undefined,
       model: row.model || "",
-      materialCode: row.materialCode || "",
       qtyRequired: row.qtyRequired || 0,
       unit: row.unit || "鏂�",
       requiredDate: row.requiredDate || "",
@@ -897,7 +912,7 @@
     });
     dialogVisible.value = true;
     fetchProductOptions();
-    fetchSpecificationOptions(row.productMaterialId);
+    fetchSpecificationOptions(row.productId);
   };
 
   // 鍒犻櫎
@@ -1178,6 +1193,7 @@
     color: #303133;
     font-size: 14px;
     min-height: 32px;
+    width: 100%;
     display: flex;
     align-items: center;
   }

--
Gitblit v1.9.3