Jelajahi Sumber

fix(质检报告审批): 兼容不良品处置台账未关联质检工单场景

- 空工单ID时不再请求质检报告接口,避免NumberFormatException,仅渲染不合格品处置单并跳过打印报告
- 处置审批直接以业务ID加载台账明细,不再依赖sourceCode查询
- 新增处置批次标识disposeBatchNo,同批明细共享,审批通过时按处置类型+批次合并生成处置入库单
lucw 4 hari lalu
induk
melakukan
e5045d9f01

+ 46 - 17
src/views/bpm/handleTask/components/qualityReportApproval/detailDialog.vue

@@ -226,7 +226,9 @@
         activeComp: 'main',
         // 质检报告数据
         template: '',
-        fileUrl: ''
+        fileUrl: '',
+        // 不良品处置台账未关联质检工单(手工新增等):此时不加载检测报告,只渲染不合格品处置单
+        isUnqualifiedDisposalNoOrder: false
       };
     },
     mounted() {
@@ -255,12 +257,26 @@
             pageNum: 1,
             size: 200
           });
-          detail = await api(data.qualityWorkOrderId);
-          detail.data.templateList.forEach((item) => {
-            if (item.inspectImage) {
-              inspectImage.push(...item.inspectImage);
-            }
-          });
+          if (data.qualityWorkOrderId) {
+            detail = await api(data.qualityWorkOrderId);
+            detail.data.templateList?.forEach((item) => {
+              if (item.inspectImage) {
+                inspectImage.push(...item.inspectImage);
+              }
+            });
+          } else {
+            // 台账未关联质检工单(如手工新增):空工单ID不能拼进URL,否则后端 Long 参数会抛
+            // NumberFormatException: For input string: "null";这里用台账数据兜底,
+            // 只渲染不合格品处置单,不加载质检报告
+            this.isUnqualifiedDisposalNoOrder = true;
+            detail = {
+              data: {
+                ...data,
+                id: '',
+                code: data.sourceCode || ''
+              }
+            };
+          }
 
           //  feedbackDepartment: '',
           //         feedbackPerson: '',
@@ -345,8 +361,11 @@
           // this.loadReportData();
           // this.loadListDetail();
 
-          let url = await getJmPrintViewUrl('qmsqualityinspectionprint');
-          this.fileUrl = `${url}?token=${getToken()}&id=${this.businessId}`;
+          // 台账未关联质检工单时没有检测报告可打印,跳过,避免用台账ID请求报告页
+          if (!this.isUnqualifiedDisposalNoOrder) {
+            let url = await getJmPrintViewUrl('qmsqualityinspectionprint');
+            this.fileUrl = `${url}?token=${getToken()}&id=${this.businessId}`;
+          }
         }
       },
       setLossNumber({
@@ -373,22 +392,32 @@
         );
       },
       async initUnqualifiedProduct() {
-        const data = await getList({
-          sourceCode: this.form.code
-        });
-        if (data.list[0]) {
-          this.unqualifiedProducts = data.list[0];
+        let unqualified = null;
+        if (this.businessType?.includes('不良品处置')) {
+          // 处置审批的台账主键就是审批业务ID,直接用它加载明细;
+          // 不走 sourceCode 查询,避免台账未关联质检工单(sourceCode 为空)时查不到台账、明细丢失
+          unqualified = { id: this.businessId };
+        } else {
+          const data = await getList({
+            sourceCode: this.form.code
+          });
+          unqualified = data.list?.[0];
+        }
+        if (unqualified) {
+          this.unqualifiedProducts = unqualified;
         }
 
         this.$nextTick(() => {
           this.$refs.unqualifiedProductRef.init({
-            id: this.unqualifiedProducts?.id,
+            id: unqualified?.id,
             qualityType:
               this.basicInfoData.qualityType || this.form.qualityType,
             workOrderCode: this.basicInfoData.code || this.form.code,
-            qualityWorkerId: this.basicInfoData.qualityWorkerId || this.form.id,
+            // 兜底场景 form.id 已被置空,避免把台账ID误当作质检工单ID写入明细
+            qualityWorkerId:
+              this.basicInfoData.qualityWorkerId || this.form.id || null,
             workOrderId:
-              this.basicInfoData.workOrderId || this.form.workOrderId,
+              this.basicInfoData.workOrderId || this.form.workOrderId || null,
             qualityResults:
               this.basicInfoData.qualityResults || this.form.qualityResults
           });

+ 30 - 1
src/views/bpm/handleTask/components/qualityReportApproval/unqualifiedProduct.vue

@@ -449,6 +449,9 @@
           ]
         },
         disposeType: '',
+        // 批量处置标识:一次处置弹窗「确定」对应一个标识,同批明细共享,
+        // 审批通过时按「处置类型 + 该标识」合并生成一张处置入库单
+        disposeBatchNo: '',
         disposeForm: {
           disposeType: '',
           sampleCondition: '',
@@ -459,7 +462,8 @@
           depotId: '',
           depotName: '',
           taskId: '',
-          keepSampleQuantity: ''
+          keepSampleQuantity: '',
+          disposeBatchNo: ''
         },
         loading: false,
         selection: [],
@@ -1003,6 +1007,27 @@
         this.disposeType = '';
         this.all = false;
         this.formData.disposalStatus = '';
+        this.disposeBatchNo = '';
+        this.disposeForm.disposeBatchNo = '';
+      },
+      /**
+       * 生成处置批次标识
+       * 规则:DB + yyyyMMddHHmmss + 4 位随机数,例如 DB202611101530251234
+       * 一次处置弹窗「确定」生成一个,批量处置写入全部选中行,单条处置只写当前行;
+       * 同一条明细被重新处置时标识覆盖为最新一次,保证以最终处置结果为准。
+       */
+      buildDisposeBatchNo() {
+        const d = new Date();
+        const pad = (n) => String(n).padStart(2, '0');
+        const ts =
+          d.getFullYear() +
+          pad(d.getMonth() + 1) +
+          pad(d.getDate()) +
+          pad(d.getHours()) +
+          pad(d.getMinutes()) +
+          pad(d.getSeconds());
+        const rand = String(Math.floor(Math.random() * 10000)).padStart(4, '0');
+        return `DB${ts}${rand}`;
       },
       // // 处置
       disposeFn(type, row) {
@@ -1013,6 +1038,10 @@
           this.current = row;
         }
         this.formData = { ...row };
+        // 每次打开处置弹窗都生成新的批次标识:批量处置时全部选中行共享同一个标识,
+        // 单条处置时该行使用自己的标识,审批通过后按标识把同批明细合并成一张处置入库单
+        this.disposeBatchNo = this.buildDisposeBatchNo();
+        this.disposeForm.disposeBatchNo = this.disposeBatchNo;
         this.dialogVisible = true;
       },