From e3a05337b453b5f09e977f4196930e8c245fb139 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期二, 15 九月 2026 10:47:49 +0800
Subject: [PATCH] fix: 1.检验保存优化 2.设备选择 3.检验复核合格不合格选择

---
 src/api/business/inspectionTask.js               |   28 ++++++
 src/views/business/inspectionView/index.vue      |   80 ++++++++++++++++++-
 src/workers/InspectionWorker.worker.js           |   16 +++
 src/views/business/inspectionTask/inspection.vue |   81 +++++++++++++++++++
 4 files changed, 194 insertions(+), 11 deletions(-)

diff --git a/src/api/business/inspectionTask.js b/src/api/business/inspectionTask.js
index c98c803..d331635 100644
--- a/src/api/business/inspectionTask.js
+++ b/src/api/business/inspectionTask.js
@@ -213,7 +213,7 @@
   return request({
     url: "/insOrderPlan/verifyPlan",
     method: "post",
-    params: data,
+    data: data,
   });
 }
 
@@ -252,6 +252,32 @@
   return saveRequest;
 }
 
+export function saveTemplateContext(data) {
+  return request({
+    url: "/insOrderPlan/saveTemplateContext",
+    method: "post",
+    data: data,
+    // 杈撳叆鍊煎拰 Worker 鍏紡缁撴灉浼氳繛缁繚瀛橈紱鐢遍〉闈繚瀛橀槦鍒椾繚璇侀『搴忥紝涓嶈蛋閫氱敤鐨� 1 绉掗槻閲嶆嫤鎴��
+    headers: { repeatSubmit: false },
+  });
+}
+
+export function getOrderDevices(query) {
+  return request({
+    url: "/insOrderPlan/orderDevices",
+    method: "get",
+    params: query,
+  });
+}
+
+export function saveOrderDevices(data) {
+  return request({
+    url: "/insOrderPlan/orderDevices",
+    method: "put",
+    data: data,
+  });
+}
+
 // 闄勪欢涓嬭浇
 export function downFile(query) {
   return request({
diff --git a/src/views/business/inspectionTask/inspection.vue b/src/views/business/inspectionTask/inspection.vue
index 94318dc..0f21557 100644
--- a/src/views/business/inspectionTask/inspection.vue
+++ b/src/views/business/inspectionTask/inspection.vue
@@ -120,6 +120,12 @@
           <el-input v-model="insOrder.remark" :disabled="state != 1" clearable placeholder="璇疯緭鍏�" size="small"
                     @blur="subOtherForm(insOrder.remark, 'remark')"></el-input>
         </el-descriptions-item>
+        <el-descriptions-item v-if="isDirectTemplateOrder()" label="璁惧" :span="2">
+          <el-select v-model="selectedDeviceIds" multiple filterable clearable size="small" placeholder="璇烽�夋嫨璁惧"
+            :disabled="state != 1" @change="saveOverviewDevices">
+            <el-option v-for="device in orderDeviceOptions" :key="device.id" :label="device.label" :value="device.id" />
+          </el-select>
+        </el-descriptions-item>
       </el-descriptions>
     </div>
     <div class="center">
@@ -579,6 +585,9 @@
   checkSubmitPlan,
   submitPlan,
   saveInsContext,
+  saveTemplateContext,
+  getOrderDevices,
+  saveOrderDevices,
   selectUserCondition,
   downFile,
   getFileList,
@@ -661,6 +670,8 @@
       comparisonList: [],
       excelMethodList: [],
       equipOptions: [],
+      orderDeviceOptions: [],
+      selectedDeviceIds: [],
       reviewLoading: false,
       reviewDia: false,
       noReason: "",
@@ -696,6 +707,8 @@
       worker0: null,
       // 妫�楠屽�兼寜瑙﹀彂椤哄簭涓茶淇濆瓨锛岄伩鍏嶅悓涓�妫�楠岄」鐨勬棫璇锋眰瑕嗙洊鏂拌姹傘��
       saveQueue: null,
+      calculationRevision: 0,
+      completedCalculationRevision: 0,
       wareLength: [],
       dataAcquisitionInfo: {},
       dataAcquisitionInfoNew: {},
@@ -1109,6 +1122,9 @@
           this.rawMaterialTag = "1";
         }
         this.getEquipOptions(1);
+        if (this.sonLaboratory === "鏂拌仛") {
+          this.loadOverviewDevices();
+        }
         // 鑾峰彇褰撳墠鏍峰搧鐨勬楠岄」
         let list = await this.getCurrentProduct(this.currentSample.id, 0);
         this.currentSample.insProduct = this.HaveJson(list);
@@ -2003,6 +2019,7 @@
         }
       }
       try {
+        const revision = ++this.calculationRevision;
         // 鍚� Worker 鍙戦�佹秷鎭紝寮�濮嬪鐞嗛�昏緫
         this.worker.postMessage(
           JSON.stringify({
@@ -2017,6 +2034,7 @@
             getDataTypeId: this.getDataTypeId,
             modelType: this.sampleProduct[0].model,
             currentInsItem: n,
+            revision: revision,
           })
         );
         // 鍏堜繚瀛樹富绾跨▼涓凡缁忚緭鍏ョ殑鍘熷鍊笺�俉orker 瀹屾垚璁$畻鍚庝細鍐嶆鍏ラ槦淇濆瓨璁$畻缁撴灉銆�
@@ -2031,6 +2049,9 @@
       // 鐩戝惉 Worker 杩斿洖鐨勭粨鏋�
       this.worker.onmessage = (event) => {
         const workerResult = JSON.parse(event.data);
+        if (workerResult.revision != null && workerResult.revision < this.calculationRevision) {
+          return;
+        }
         this.result = workerResult;
         switch (workerResult.method) {
           case "saveInsContext":
@@ -2043,6 +2064,10 @@
               );
               this.param = resultValue.param;
               this.saveInsContext();
+              this.completedCalculationRevision = Math.max(
+                this.completedCalculationRevision,
+                workerResult.revision || 0
+              );
             });
             break;
           case "tableList":
@@ -2353,7 +2378,17 @@
       const param = {};
       this.tableList.forEach((a) => {
         param[a.templateId] = {};
-        a.template.forEach((cell) => {
+        // Worker 鍥炰紶鍚� arr 鏄〉闈笂鐨勬渶鏂板璞★紝template 浠嶅彲鑳戒繚鐣欒绠楀墠鐨勬棫鍊笺��
+        const cells = a.arr && a.arr.length
+          ? a.arr.reduce((all, row) => all.concat(row), [])
+          : a.template;
+        const resultHeader = cells.find((cell) =>
+          cell.v && String(cell.v.v || "").trim() === "妫�楠岀粨鏋�"
+        );
+        const exportRows = new Set(cells.filter((cell) =>
+          cell.v && cell.v.ps && cell.v.ps.value === "瀵煎嚭鍊�"
+        ).map((cell) => cell.r));
+        cells.forEach((cell) => {
           const isEditable =
             cell.v.ps != undefined &&
             typeof cell.v.ps.value === "string" &&
@@ -2361,10 +2396,12 @@
               cell.v.ps.value === "璁$畻鍊�" ||
               cell.v.ps.value === "鏈�缁堝��" ||
               cell.v.ps.value === "璁惧鍚嶇О");
-          if (!isEditable) {
+          const isExportResult = resultHeader && exportRows.has(cell.r) && cell.c === resultHeader.c;
+          if (!isEditable && !isExportResult) {
             return;
           }
           if (
+            isEditable &&
             cell.v.ps.value.includes("妫�楠屽��") &&
             (cell.v.v === "" || cell.v.v === null || cell.v.v === undefined)
           ) {
@@ -2410,7 +2447,14 @@
         const previousSave = this.saveQueue || Promise.resolve();
         this.saveQueue = previousSave
           .catch(() => undefined)
-          .then(() => saveInsContext(payload))
+          .then(() => this.isDirectTemplateOrder()
+            ? saveTemplateContext({
+                orderId: this.orderId,
+                sampleId: this.currentSample.id,
+                templateId: this.currentTable,
+                values: param[this.currentTable] || {},
+              })
+            : saveInsContext(payload))
           .then(() => {
             this.$message.success("宸蹭繚瀛�");
           })
@@ -2433,6 +2477,20 @@
       }
     },
     async waitForPendingSaves() {
+      const targetRevision = this.calculationRevision;
+      if (this.completedCalculationRevision < targetRevision) {
+        await new Promise((resolve) => {
+          const startedAt = Date.now();
+          const waitWorker = () => {
+            if (this.completedCalculationRevision >= targetRevision || Date.now() - startedAt > 5000) {
+              resolve();
+              return;
+            }
+            setTimeout(waitWorker, 20);
+          };
+          waitWorker();
+        });
+      }
       if (this.saveQueue) {
         await this.saveQueue;
       }
@@ -2458,6 +2516,23 @@
       // 閫夋嫨銆佺Щ闄ゃ�佹竻绌哄潎鐢� change 浜嬩欢瑙﹀彂锛岀珛鍗充繚瀛樸��
       this.saveInsContext();
     },
+    isDirectTemplateOrder() {
+      return this.sonLaboratory === "鏂拌仛" && this.currentSample &&
+        (this.currentSample.insProduct || []).some((product) => product.templateRowIndex != null);
+    },
+    loadOverviewDevices() {
+      Promise.all([search({ status: 0 }), getOrderDevices({ orderId: this.orderId })]).then(([devices, selected]) => {
+        this.orderDeviceOptions = (devices.data || []).map((device) => ({
+          id: device.id,
+          label: `${device.deviceName}--${device.managementNumber}`,
+        }));
+        this.selectedDeviceIds = selected.data || [];
+      });
+    },
+    saveOverviewDevices() {
+      return saveOrderDevices({ orderId: this.orderId, deviceIds: this.selectedDeviceIds })
+        .then(() => this.$message.success("璁惧宸蹭繚瀛�"));
+    },
     getAuthorizedPerson() {
       selectUserCondition({ type: 1 }).then((res) => {
         let data = [];
diff --git a/src/views/business/inspectionView/index.vue b/src/views/business/inspectionView/index.vue
index f086612..0d4eefa 100644
--- a/src/views/business/inspectionView/index.vue
+++ b/src/views/business/inspectionView/index.vue
@@ -74,6 +74,12 @@
                     @blur="subOtherForm(insOrder.remark, 'remark')"></el-input>
           <!-- <el-tag v-if="currentKey">{{ insOrder.remark }}</el-tag> -->
         </el-form-item>
+        <el-form-item v-if="isDirectTemplateOrder()" label="妫�楠岀粨璁�:">
+          <el-radio-group v-model="reviewInsResult" :disabled="state != 2">
+            <el-radio :label="1">鍚堟牸</el-radio>
+            <el-radio :label="0">涓嶅悎鏍�</el-radio>
+          </el-radio-group>
+        </el-form-item>
       </el-form>
     </div>
     <div class="center">
@@ -205,8 +211,8 @@
                           " />
                     <span v-else-if="getInspectionValueType(n.i) == 4"
                           :style="`font-family:${n.v.ff} !important;`">/</span>
-                  </template>
-                  <template v-else-if="
+                    </template>
+                    <template v-else-if="
                       n.v.ps != undefined && n.v.ps.value === '璁惧鍚嶇О'
                     ">
                     <el-select v-model="n.v.v" :disabled="state > 1" class="table_input" filterable multiple
@@ -486,6 +492,7 @@
   checkSubmitPlan,
   submitPlan,
   saveInsContext,
+  saveTemplateContext,
   selectUserCondition,
   downFile,
   getFileList,
@@ -546,6 +553,8 @@
       ps: {},
       param: {},
       saveQueue: null,
+      calculationRevision: 0,
+      completedCalculationRevision: 0,
       currentKey: 1,
       currentKey0: 1,
       currentKey1: 1,
@@ -556,6 +565,7 @@
       reviewLoading: false,
       reviewDia: false,
       noReason: "",
+      reviewInsResult: null,
       tableWidth: 1000,
       currentTable: null,
       tableLists: [],
@@ -875,13 +885,15 @@
       this.checkUser = "";
     },
     // 鍒锋柊椤甸潰
-    refreshView() {
+    async refreshView() {
+      await this.waitForPendingSaves();
       this.loading = true;
       doInsOrder({
         id: this.id,
         laboratory: this.sonLaboratory,
       }).then(async (res) => {
         this.insOrder = res.data.insOrder;
+        this.reviewInsResult = this.insOrder.insResult;
         this.supplierDensity = res.data.supplierDensity;
         this.getList()
         this.urgentList.forEach((m) => {
@@ -1802,6 +1814,7 @@
         }
       }
       try {
+        const revision = ++this.calculationRevision;
         // 鍚� Worker 鍙戦�佹秷鎭紝寮�濮嬪鐞嗛�昏緫
         this.worker.postMessage(
           JSON.stringify({
@@ -1816,6 +1829,7 @@
             getDataTypeId: this.getDataTypeId,
             modelType: this.sampleProduct[0].model,
             currentInsItem: n,
+            revision: revision,
           })
         );
         // 鍏堜繚瀛樹富绾跨▼涓凡缁忚緭鍏ョ殑鍘熷鍊笺�俉orker 瀹屾垚璁$畻鍚庝細鍐嶆鍏ラ槦淇濆瓨璁$畻缁撴灉銆�
@@ -1830,6 +1844,9 @@
       // 鐩戝惉 Worker 杩斿洖鐨勭粨鏋�
       this.worker.onmessage = (event) => {
         const workerResult = JSON.parse(event.data);
+        if (workerResult.revision != null && workerResult.revision < this.calculationRevision) {
+          return;
+        }
         this.result = workerResult;
         switch (workerResult.method) {
           case "saveInsContext":
@@ -1842,6 +1859,10 @@
               );
               this.param = resultValue.param;
               this.saveInsContext();
+              this.completedCalculationRevision = Math.max(
+                this.completedCalculationRevision,
+                workerResult.revision || 0
+              );
             });
             break;
           case "tableList":
@@ -1961,6 +1982,10 @@
     upInsReview(e) {
       if (e == 1) {
         // 閫氳繃
+        if (this.isDirectTemplateOrder() && this.reviewInsResult !== 0 && this.reviewInsResult !== 1) {
+          this.$message.error("璇烽�夋嫨妫�楠岀粨璁�");
+          return;
+        }
         this.reviewLoading = true;
         verifyPlan({
           orderId: this.orderId,
@@ -1968,6 +1993,7 @@
           laboratory: this.sonLaboratory,
           tell: null,
           userId: this.checkUser,
+          insResult: this.isDirectTemplateOrder() ? this.reviewInsResult : null,
         }).then((res) => {
           if (res.code === 200) {
             this.$message.success("鎿嶄綔鎴愬姛");
@@ -2130,7 +2156,17 @@
       const param = {};
       this.tableList.forEach((a) => {
         param[a.templateId] = {};
-        a.template.forEach((cell) => {
+        // Worker 鍥炰紶鍚� arr 鏄〉闈笂鐨勬渶鏂板璞★紝template 浠嶅彲鑳戒繚鐣欒绠楀墠鐨勬棫鍊笺��
+        const cells = a.arr && a.arr.length
+          ? a.arr.reduce((all, row) => all.concat(row), [])
+          : a.template;
+        const resultHeader = cells.find((cell) =>
+          cell.v && String(cell.v.v || "").trim() === "妫�楠岀粨鏋�"
+        );
+        const exportRows = new Set(cells.filter((cell) =>
+          cell.v && cell.v.ps && cell.v.ps.value === "瀵煎嚭鍊�"
+        ).map((cell) => cell.r));
+        cells.forEach((cell) => {
           const isEditable =
             cell.v.ps != undefined &&
             typeof cell.v.ps.value === "string" &&
@@ -2138,10 +2174,12 @@
               cell.v.ps.value === "璁$畻鍊�" ||
               cell.v.ps.value === "鏈�缁堝��" ||
               cell.v.ps.value === "璁惧鍚嶇О");
-          if (!isEditable) {
+          const isExportResult = resultHeader && exportRows.has(cell.r) && cell.c === resultHeader.c;
+          if (!isEditable && !isExportResult) {
             return;
           }
           if (
+            isEditable &&
             cell.v.ps.value.includes("妫�楠屽��") &&
             (cell.v.v === "" || cell.v.v === null || cell.v.v === undefined)
           ) {
@@ -2187,7 +2225,14 @@
         const previousSave = this.saveQueue || Promise.resolve();
         this.saveQueue = previousSave
           .catch(() => undefined)
-          .then(() => saveInsContext(payload))
+          .then(() => this.isDirectTemplateOrder()
+            ? saveTemplateContext({
+                orderId: this.orderId,
+                sampleId: this.currentSample.id,
+                templateId: this.currentTable,
+                values: param[this.currentTable] || {},
+              })
+            : saveInsContext(payload))
           .then(() => {
             this.$message.success("宸蹭繚瀛�");
           })
@@ -2230,6 +2275,29 @@
       // 閫夋嫨銆佺Щ闄ゃ�佹竻绌哄潎鐢� change 浜嬩欢瑙﹀彂锛岀珛鍗充繚瀛樸��
       this.saveInsContext();
     },
+    isDirectTemplateOrder() {
+      return this.sonLaboratory === "鏂拌仛" && this.currentSample &&
+        (this.currentSample.insProduct || []).some((product) => product.templateRowIndex != null);
+    },
+    async waitForPendingSaves() {
+      const targetRevision = this.calculationRevision;
+      if (this.completedCalculationRevision < targetRevision) {
+        await new Promise((resolve) => {
+          const startedAt = Date.now();
+          const waitWorker = () => {
+            if (this.completedCalculationRevision >= targetRevision || Date.now() - startedAt > 5000) {
+              resolve();
+              return;
+            }
+            setTimeout(waitWorker, 20);
+          };
+          waitWorker();
+        });
+      }
+      if (this.saveQueue) {
+        await this.saveQueue;
+      }
+    },
     getAuthorizedPerson() {
       selectUserCondition({ type: 1 }).then((res) => {
         let data = [];
diff --git a/src/workers/InspectionWorker.worker.js b/src/workers/InspectionWorker.worker.js
index a8756a7..f838022 100644
--- a/src/workers/InspectionWorker.worker.js
+++ b/src/workers/InspectionWorker.worker.js
@@ -35,6 +35,8 @@
 // 褰撳墠杩欐杈撳叆瀵瑰簲鐨勫師濮嬫楠岄」銆傝绠楄繃绋嬩腑 pId 浼氬垏鎹㈠埌涓嬫父璁$畻椤癸紝
 // 淇濆瓨鏃跺繀椤诲悓鏃跺甫鍥炲師濮嬫楠岄」锛屽惁鍒欏彧浼氫繚瀛樿绠楃粨鏋溿��
 let sourceInsItemId = null;
+// 褰撳墠娑堟伅鐗堟湰銆俉orker 鍗曠嚎绋嬩覆琛屽鐞嗘秷鎭紝渚涢�掑綊鍏紡璁$畻瀹屾垚鍚庡洖浼犵粰涓荤嚎绋嬨��
+let currentRevision = null;
 
 /**
  * 鐢熸垚妯℃澘缁撴瀯绛惧悕
@@ -68,6 +70,7 @@
 self.onmessage = function (event) {
   // 淇濆瓨涓荤嚎绋嬩紶杩囨潵鐨勫��
   const data = JSON.parse(event.data);
+  currentRevision = data.revision;
   // 妯℃澘鍐呭鍙樹簡(涓嶅彧鏄ā鏉縤d鍙樹簡)涔熻鍒锋柊琛ㄦ牸,鍚﹀垯鏀瑰畬妯$増鍚� Worker 浠嶇敤鏃фā鏉胯绠楀苟鎶婃棫鐗堝紡鍥炲啓椤甸潰
   const nextTemplateSig = buildTemplateSig(data.tableList);
   if (
@@ -468,6 +471,7 @@
     // 璧嬪�间紶閫掑埌涓荤嚎绋嬬殑鏁版嵁锛宮ethod锛歴aveInsContext琛ㄧず姝ゆ秷鎭渶瑕佷繚瀛樻暟鎹�
     result = {
       method: "saveInsContext",
+      revision: currentRevision,
       value: {
         tableList, // 琛ㄦ牸鏁版嵁
         param: getParam(), //浼犵粰鍚庣鐨勫弬鏁�
@@ -483,6 +487,7 @@
   // 璧嬪�煎绾跨▼浼犺緭鏁版嵁
   result = {
     method: "tableList",
+    revision: currentRevision,
     value: tableList,
   };
   // 鍙戦�佷富绾跨▼鏁版嵁
@@ -589,6 +594,13 @@
   const resultParam = {};
   tableList.forEach((t) => {
     resultParam[t.templateId] = {};
+    const cells = (t.arr || []).reduce((all, row) => all.concat(row), []);
+    const resultHeader = cells.find((cell) =>
+      cell.v && String(cell.v.v || "").trim() === "妫�楠岀粨鏋�"
+    );
+    const exportRows = new Set(cells.filter((cell) =>
+      cell.v && cell.v.ps && cell.v.ps.value === "瀵煎嚭鍊�"
+    ).map((cell) => cell.r));
     (t.arr || []).forEach((a) => {
       a.forEach((b) => {
         const isEditable =
@@ -598,10 +610,12 @@
             b.v.ps.value === "璁$畻鍊�" ||
             b.v.ps.value === "鏈�缁堝��" ||
             b.v.ps.value === "璁惧鍚嶇О");
-        if (!isEditable) {
+        const isExportResult = resultHeader && exportRows.has(b.r) && b.c === resultHeader.c;
+        if (!isEditable && !isExportResult) {
           return;
         }
         if (
+          isEditable &&
           b.v.ps.value.includes("妫�楠屽��") &&
           (b.v.v === "" || b.v.v === null || b.v.v === undefined)
         ) {

--
Gitblit v1.9.3