From a74fb3a81cce704299f765078ababc7a743bab9d Mon Sep 17 00:00:00 2001
From: ZN <zhang_12370@163.com>
Date: 星期四, 19 三月 2026 16:45:34 +0800
Subject: [PATCH] feat(productionReporting): 添加工单报工审核功能

---
 src/views/productionManagement/productionReporting/index.vue |  172 ++++++++++++++++++++++++++++++++++++++++++-
 src/views/productionManagement/workOrder/index.vue           |   41 ++++++++--
 src/api/productionManagement/productionProductMain.js        |    9 ++
 3 files changed, 210 insertions(+), 12 deletions(-)

diff --git a/src/api/productionManagement/productionProductMain.js b/src/api/productionManagement/productionProductMain.js
index 0493f8b..24976b6 100644
--- a/src/api/productionManagement/productionProductMain.js
+++ b/src/api/productionManagement/productionProductMain.js
@@ -9,3 +9,12 @@
         params: query,
     });
 }
+
+// 鎶ュ伐瀹℃壒
+export function productAudit(data) {
+    return request({
+        url: "/productionProductMain/productAudit",
+        method: "post",
+        data,
+    });
+}
diff --git a/src/views/productionManagement/productionReporting/index.vue b/src/views/productionManagement/productionReporting/index.vue
index 0b42dae..f06131a 100644
--- a/src/views/productionManagement/productionReporting/index.vue
+++ b/src/views/productionManagement/productionReporting/index.vue
@@ -19,6 +19,12 @@
                     style="width: 200px;"
                     @change="handleQuery" />
         </el-form-item>
+        <el-form-item label="瀹℃牳鐘舵��:">
+          <el-select v-model="searchForm.auditStatus" placeholder="璇烽�夋嫨" style="width: 200px;" @change="handleQuery">
+              <el-option v-for="item in auditStatusOptions" :key="item.value" :label="item.label" :value="item.value">
+              </el-option>
+          </el-select>
+        </el-form-item>
         <el-form-item>
           <el-button type="primary"
                      @click="handleQuery">鎼滅储</el-button>
@@ -119,6 +125,41 @@
         </template>
       </PIMTable>
     </div>
+    <el-dialog
+      v-model="auditDialogVisible"
+      title="瀹℃牳鎰忚"
+      width="1200px"
+      :close-on-click-modal="false"
+    >
+      <!-- 瀹℃牳琛ㄥ崟 -->
+      <div style=" padding: 15px; border-radius: 4px;">
+        <el-form ref="auditFormRef" :model="form" :rules="auditFormRules" label-width="100px">
+          <el-form-item label="瀹℃牳缁撴灉" prop="auditResult">
+            <el-radio-group v-model="form.auditResult" @change="handleAuditResultChange" size="large">
+              <el-radio label=1 >閫氳繃</el-radio>
+              <el-radio label=2 >涓嶉�氳繃</el-radio>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item label="澶囨敞鎰忚" prop="remarks">
+            <el-input
+              v-model="form.remarks"
+              type="textarea"
+              :rows="4"
+              placeholder="璇疯緭鍏ュ娉ㄦ垨鎰忚锛堜笉閫氳繃鏃朵负蹇呭~锛�"
+              maxlength="500"
+              show-word-limit
+            />
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button type="primary" @click="submitAudit">鎻愪氦瀹℃牳</el-button>
+          <el-button :disabled="auditLoading" @click="auditDialogVisible = false">鍙栨秷</el-button>
+        </span>
+      </template>
+    </el-dialog>
     <form-dia ref="formDia"
               @close="handleQuery"></form-dia>
     <input-modal v-if="isShowInput"
@@ -128,15 +169,15 @@
 </template>
 
 <script setup>
-  import { onMounted, ref } from "vue";
+  import { onMounted, ref, reactive, toRefs, nextTick, getCurrentInstance } from "vue";
   import FormDia from "@/views/productionManagement/productionReporting/components/formDia.vue";
-  import { ElMessageBox } from "element-plus";
+  import { ElMessageBox, ElMessage } from "element-plus";
   import {
     productionReportUpdate,
     workListPageById,
     productionReportDelete,
   } from "@/api/productionManagement/productionReporting.js";
-  import { productionProductMainListPage } from "@/api/productionManagement/productionProductMain.js";
+  import { productionProductMainListPage, productAudit } from "@/api/productionManagement/productionProductMain.js";
   import { userListNoPageByTenantId } from "@/api/system/user.js";
   import InputModal from "@/views/productionManagement/productionReporting/Input.vue";
 
@@ -145,12 +186,22 @@
       nickName: "",
       workOrderNo: "",
       workOrderStatus: "",
+      auditStatus: "", // 瀹℃牳鐘舵��
     },
   });
   const { searchForm } = toRefs(data);
   const expandedRowKeys = ref([]);
+  const auditDialogVisible = ref(false);
+  const auditRowData = ref(null);
+  const auditTableData = ref([]);
+  const auditLoading = ref(false);
   const expandData = ref([]);
   const userList = ref([]);
+  const auditStatusOptions = ref([
+    { label: "鏈鏍�", value: 0 },
+    { label: "閫氳繃", value: 1 },
+    { label: "涓嶉�氳繃", value: 2 },
+  ]);
   const tableColumn = ref([
     {
       label: "鎶ュ伐鍗曞彿",
@@ -202,7 +253,25 @@
       prop: "unit",
       width: 120,
     },
-    
+    {
+      label: "瀹℃牳浜�",
+      prop: "auditUserName",
+      width: 120,
+    },
+    {
+      label: "瀹℃牳鐘舵��",
+      prop: "auditStatus",
+      width: 120,
+      dataType: "tag",
+      formatData: val => {
+        const statusMap = { 0: "鏈鏍�", 1: "閫氳繃", 2: "涓嶉�氳繃" };
+        return statusMap[val] ?? "鏈煡";
+      },
+      formatType: val => {
+        const typeMap = { 0: "info", 1: "success", 2: "danger" };
+        return typeMap[val] ?? "";
+      },
+    },
     {
       label: "鍒涘缓鏃堕棿",
       prop: "createTime",
@@ -213,6 +282,7 @@
       label: "鎿嶄綔",
       align: "center",
       fixed: "right",
+      width: 200,
       operation: [
         {
           name: "鏌ョ湅鎶曞叆",
@@ -220,6 +290,15 @@
           clickFun: row => {
             showInput(row);
           },
+        },
+        {
+          name:"瀹℃牳",
+          // 榛勮壊
+          color: "#E6A23C",
+          clickFun: row => {
+            handleAudit(row);
+          },
+          showHide: row => Number(row?.auditStatus) === 0, // 浠呭綋鏈鏍告椂鏄剧ず瀹℃牳鎸夐挳
         },
         {
           name: "鍒犻櫎",
@@ -242,6 +321,26 @@
   });
   const formDia = ref();
   const { proxy } = getCurrentInstance();
+  const auditFormRef = ref(null);
+  const auditFormRules = ref({
+    auditResult: [{ required: true, message: "璇烽�夋嫨瀹℃牳缁撴灉", trigger: "change" }],
+    remarks: [
+      {
+        validator: (rule, value, callback) => {
+          if (form.value.auditResult === "2" && (!value || value.trim() === "")) {
+            callback(new Error("涓嶉�氳繃鏃跺繀椤诲~鍐欏娉ㄦ垨鎰忚"));
+          } else {
+            callback();
+          }
+        },
+        trigger: ["change", "blur"],
+      },
+    ],
+  });
+  const form = ref({
+    auditResult: 1,
+    remarks: "",
+  });
 
   // 鏌ヨ鍒楄〃
   /** 鎼滅储鎸夐挳鎿嶄綔 */
@@ -398,6 +497,71 @@
     isShowingId.value = row.id;
   };
 
+   // 瀹℃牳
+  const handleAudit = (row) => {
+    if (Number(row?.auditStatus) === 1) {
+      ElMessage.warning("璇ュ伐鍗曞凡瀹℃牳");
+      return;
+    }
+    // 閲嶇疆琛ㄥ崟锛岄粯璁ら�夋嫨閫氳繃
+    form.value = {
+      auditResult: "1",
+      remarks: "",
+    };
+    auditRowData.value = row;
+    const workOrderNo = row?.workOrderNo;
+    const related = workOrderNo
+      ? tableData.value.filter(r => r?.workOrderNo === workOrderNo)
+      : [];
+    auditTableData.value = related.length > 0 ? related : [row];
+    auditDialogVisible.value = true;
+    nextTick(() => {
+      auditFormRef.value?.clearValidate();
+    });
+  };
+
+  // 瀹℃牳缁撴灉鍙樻洿
+  const handleAuditResultChange = () => {
+    if (form.value.auditResult === "1") {
+      // 鍒囨崲涓洪�氳繃鏃舵竻闄ゅ娉ㄦ牎楠�
+      auditFormRef.value?.clearValidate("remarks");
+    } else {
+      // 鍒囨崲涓轰笉閫氳繃鏃堕噸鏂拌Е鍙戝娉ㄦ牎楠�
+      auditFormRef.value?.validateField("remarks");
+    }
+  };
+
+  // 鎻愪氦瀹℃牳
+  const submitAudit = (auditResult) => {
+    auditFormRef.value?.validate().then(() => {
+      auditLoading.value = true;
+      const auditData = {
+        id: auditRowData.value.id,
+        auditStatus: Number(form.value.auditResult),
+        auditOpinion: form.value.remarks,
+      };
+      // 璋冪敤鎶ュ伐瀹℃壒API
+      productAudit(auditData)
+        .then(res => {
+          if (res.code === 200) {
+            proxy.$modal.msgSuccess(auditResult === 1 ? "瀹℃牳閫氳繃" : "瀹℃牳涓嶉�氳繃");
+            auditDialogVisible.value = false;
+            getList();
+          } else {
+            proxy.$modal.msgError(res.msg || "瀹℃牳澶辫触");
+          }
+        })
+        .catch(err => {
+          proxy.$modal.msgError("瀹℃牳澶辫触");
+        })
+        .finally(() => {
+          auditLoading.value = false;
+        });
+    }).catch(() => {
+      // 楠岃瘉澶辫触
+    });
+  };
+
   // 瀵煎嚭
   const handleOut = () => {
     ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
diff --git a/src/views/productionManagement/workOrder/index.vue b/src/views/productionManagement/workOrder/index.vue
index 902ca25..d0740dc 100644
--- a/src/views/productionManagement/workOrder/index.vue
+++ b/src/views/productionManagement/workOrder/index.vue
@@ -209,6 +209,19 @@
                        :value="user.userId" />
           </el-select>
         </el-form-item>
+        <el-form-item label="瀹℃牳浜�" prop="auditUserId">
+          <el-select v-model="reportForm.auditUserId"
+                     style="width: 300px"
+                     placeholder="璇烽�夋嫨瀹℃牳浜�"
+                     clearable
+                     filterable
+                     @change="handleReviewerIdChange">
+            <el-option v-for="user in userOptions"
+                       :key="user.userId"
+                       :label="user.nickName"
+                       :value="user.userId" />
+          </el-select>
+        </el-form-item>
       </el-form>
       <template #footer>
         <span class="dialog-footer">
@@ -373,14 +386,14 @@
           },
           disabled: row => row.planQuantity <= 0,
         },
-        {
-          name:"瀹℃牳",
-          color: "#f56c6c",
-          clickFun: row => {
-            handleAudit(row);
-          },
-          disabled: row => Number(row?.auditStatus) === 1,
-        }
+        // {
+        //   name:"瀹℃牳",
+        //   color: "#f56c6c",
+        //   clickFun: row => {
+        //     handleAudit(row);
+        //   },
+        //   disabled: row => Number(row?.auditStatus) === 1,
+        // }
       ],
     },
   ]);
@@ -503,6 +516,7 @@
   const reportFormRules = {
     quantity: [{ required: true, validator: validateQuantity, trigger: "blur" }],
     scrapQty: [{ validator: validateScrapQty, trigger: "blur" }],
+    auditUserId: [{ required: true, message: "璇烽�夋嫨瀹℃牳浜�", trigger: "change" }],
   };
 
   // 澶勭悊鏈鐢熶骇鏁伴噺杈撳叆锛岄檺鍒跺繀椤诲ぇ浜庣瓑浜�1
@@ -829,6 +843,17 @@
       reportForm.userName = "";
     }
   };
+  // 瀹℃牳浜�
+  const handleReviewerIdChange = userId => {
+    if (userId) {
+      const selectedUser = userOptions.value.find(user => user.userId === userId);
+      if (selectedUser) {
+        reportForm.auditUserName = selectedUser.nickName;
+      }
+    } else {
+      reportForm.auditUserName = "";
+    }
+  }
 
   onMounted(() => {
     getList();

--
Gitblit v1.9.3