From 39154a82354b08c2449918c0665457fdb2701b9b Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期五, 16 十月 2026 16:02:23 +0800
Subject: [PATCH] 设备模块各标签页弹窗新增草稿自动保存与恢复:编辑或录入数据中途关闭/刷新页面,再次打开同一弹窗时自动恢复未保存的编辑内容(弹窗显示"已恢复上次未保存的编辑内容"提示),保存成功后草稿自动清除;新增 src/mixins/draftSave.js 同时清理设备死代码:management.vue 数采配置旧弹窗及其提交方法、calibration.vue 被注释的导出按钮、device.js 中 numberCollect/deviceMetricRecordExport 两个死接口定义

---
 src/views/CNAS/resourceDemand/device/component/files.vue |  484 +++++++++++++++++++++++++++++++++++------------------
 1 files changed, 320 insertions(+), 164 deletions(-)

diff --git a/src/views/CNAS/resourceDemand/device/component/files.vue b/src/views/CNAS/resourceDemand/device/component/files.vue
index 4904357..bb231a9 100644
--- a/src/views/CNAS/resourceDemand/device/component/files.vue
+++ b/src/views/CNAS/resourceDemand/device/component/files.vue
@@ -5,7 +5,7 @@
       <h4><span class="line"></span><span>璁惧妗f</span></h4>
       <div class="btns">
         <el-button type="primary" size="small" @click="openEditForm" style="">淇妗f</el-button>
-        <el-button type="primary" size="small" @click="dialogVisible1 = true" style="">娣诲姞闄勪欢</el-button>
+        <el-button type="primary" size="small" @click="openAddFileDia" style="">娣诲姞闄勪欢</el-button>
         <el-button type="primary" size="small" @click="deviceDialog = true" style="">鏌ョ湅璁惧浜岀淮鐮�</el-button>
         <el-button type="primary" size="small" @click="handleDownOne" style="">瀵煎嚭</el-button>
       </div>
@@ -38,10 +38,6 @@
           <div class="form-item">
             <label>绠$悊缂栧彿</label>
             <p>{{ Mdata.managementNumber }}</p>
-          </div>
-          <div class="form-item">
-            <label>鎵�灞為儴闂�</label>
-            <p>{{ Mdata.laboratoryName }}</p>
           </div>
           <div class="form-item">
             <label>鐢熶骇鍘傚</label>
@@ -184,156 +180,199 @@
     <!-- 淇 -->
     <el-dialog title="妗f淇" top="5vh" v-model="dialogVisible" width="70%" @open="openFileRevisionDialog"
       :before-close="handleClose">
-      <el-row style="display:flex;justify-content: space-around;max-height: 75vh;overflow-y: auto;">
-        <!-- 宸﹁竟甯冨眬 -->
-        <el-col :span="7">
-          <el-col>
-            <!-- 鍥剧墖 -->
-            <el-image class="img" style="width:100%;height: 320px;margin-bottom:16px"
-              :src="javaApi + '/img/' + editData.imageUpload">
-              <template #error><div  class="image-error" style="width: calc(100% - 2px);
+      <div style="max-height: 75vh;overflow-y: auto;">
+      <!-- 椤堕儴锛氬浘鐗� + 鍩烘湰淇℃伅 -->
+      <el-row>
+        <el-col :span="7" style="padding-right: 20px;">
+          <!-- 鍥剧墖 -->
+          <el-image class="img" style="width:100%;height: 320px;"
+            :src="javaApi + '/img/' + editData.imageUpload">
+            <template #error><div  class="image-error" style="width: calc(100% - 2px);
             height: 318px;
             border-radius: 16px;
             display: flex;
             align-items: center;
             justify-content: center;
-            border: 1px solid #EEEEEE;">
-                <lims-icon name="el-icon-picture-outline" style="font-size:60px;color:#666666;"></lims-icon>
-              </div></template>
-            </el-image>
-            <!-- 琛ㄥ崟 -->
-            <el-form :model="editData" label-width="120px" ref="rules1" :rules="rules1">
+            border: 1px solid var(--lims-divider);">
+              <lims-icon name="el-icon-picture-outline" style="font-size:60px;color:var(--lims-text-2);"></lims-icon>
+            </div></template>
+          </el-image>
+          <!-- 鍥剧墖涓婁紶 -->
+          <div style="margin-top: 12px;text-align: center;">
+            <div v-show="editData.imageName" class="picName">{{ editData.imageName }}</div>
+            <el-upload :action="action" :on-success="handleSuccessUpImg2" :show-file-list="false"
+              accept='image/jpg,image/jpeg,image/png' :headers="uploadHeader" :on-change="beforeUpload"
+              :on-error="onError" ref='upload' class="avatar-uploader">
+              <img v-if="editData.imageUpload" :src="javaApi + '/img/' + editData.imageUpload" class="avatar">
+              <lims-icon name="el-icon-plus" v-else class="avatar-uploader-icon"></lims-icon>
+            </el-upload>
+          </div>
+        </el-col>
+        <el-col :span="17">
+          <!-- 鍩烘湰淇℃伅 -->
+          <div class="section-title" style="margin-top: 0;">鍩烘湰淇℃伅</div>
+          <el-form :model="editData" label-width="120px" ref="rules1" :rules="rules1">
+            <div class="form-row">
               <el-form-item label="浠櫒鍚嶇О:" prop="deviceName">
                 <el-input v-model="editData.deviceName" size="small"></el-input>
               </el-form-item>
               <el-form-item label="浠櫒鍚嶇ОEN:" prop="enDeviceName">
                 <el-input v-model="editData.enDeviceName" size="small"></el-input>
               </el-form-item>
+            </div>
+            <div class="form-row">
               <el-form-item label="瑙勬牸鍨嬪彿:" prop="specificationModel">
                 <el-input v-model="editData.specificationModel" size="small"></el-input>
               </el-form-item>
               <el-form-item label="鐢熶骇鍘傚:">
                 <el-input v-model="editData.manufacturer" size="small"></el-input>
               </el-form-item>
-            </el-form>
-          </el-col>
-        </el-col>
-        <!-- 涓棿甯冨眬 -->
-        <el-col :span="7">
-          <el-form :model="editData" label-width="116px" ref="rules2" :rules="rules1">
-            <el-form-item label="鏍″噯鏈嶅姟鏈烘瀯:">
-              <el-input v-model="editData.calibrationServices" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="璧勪骇缂栫爜:">
-              <el-input v-model="editData.assetCode" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="浜у湴:">
-              <el-input v-model="editData.origin" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="鍑哄巶缂栧彿:">
-              <el-input v-model="editData.factoryNo" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="绠$悊缂栧彿:" prop="managementNumber">
-              <el-input v-model="editData.managementNumber" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="璐疆鏃ユ湡:">
-              <el-date-picker style="width:100%" v-model="editData.acquisitionDate" type="date" format="YYYY-MM-DD"
-                value-format="YYYY-MM-DD HH:mm:ss" size="small" placeholder="閫夋嫨鏃ユ湡">
-              </el-date-picker>
-            </el-form-item>
-            <el-form-item label="鏍″噯鏈夋晥鏈�:" prop="activationDate">
-              <el-date-picker style="width:100%" v-model="editData.activationDate" type="date" format="YYYY-MM-DD"
-                value-format="YYYY-MM-DD HH:mm:ss" size="small" placeholder="閫夋嫨鏃ユ湡">
-              </el-date-picker>
-            </el-form-item>
-            <el-form-item label="璐熻矗浜�:">
-              <el-select v-model="editData.equipmentManager" placeholder="璇烽�夋嫨" size="small" style="width:100%">
-                <el-option v-for="item in responsiblePersonList" :key="item.name" :label="item.name" :value="item.id">
-                </el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item label="瀛樻斁鐐�:">
-              <el-input v-model="editData.storagePoint" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="鎶�鏈寚鏍�:">
-              <el-input v-model="editData.technicalIndicators" :rows="7" type="textarea" size="small"></el-input>
-            </el-form-item>
-          </el-form>
-        </el-col>
-        <!-- 鍙宠竟甯冨眬 -->
-        <el-col :span="7">
-          <el-form :model="editData" label-width="140px" ref="ruleForm" :rules="rules1">
-            <!-- 瀹為獙瀹ゅ垪琛� -->
-            <el-form-item label="鎵�灞為儴闂�:" prop="subordinateDepartmentsId">
-              <el-select v-model="editData.subordinateDepartmentsId" placeholder="璇烽�夋嫨" size="small" style="width:100%">
-                <el-option v-for="item in subordinateDepartmentsList" :key="item.value" :label="item.label"
-                  :value="item.value">
-                </el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item label="妫�娴嬮」鐩�:">
-              <el-cascader v-model="editData.insProductIds" :options="options" :show-all-levels="false" :props="props"
-                placeholder="璇烽�夋嫨" size="small" style="width:100%;" :collapse-tags="true" separator="," filterable
-                clearable></el-cascader>
-            </el-form-item>
-            <el-form-item label="鏈�杩戞牎鍑嗘棩鏈�:">
-              <el-date-picker style="width:100%" v-model="editData.lastCalibrationDate" format="YYYY-MM-DD"
-                value-format="YYYY-MM-DD HH:mm:ss" type="date" size="small" placeholder="閫夋嫨鏃ユ湡">
-              </el-date-picker>
-            </el-form-item>
-            <el-form-item label="涓嬫鏍″噯鏃ユ湡:">
-              <el-date-picker style="width:100%" v-model="editData.nextCalibrationDate" format="YYYY-MM-DD"
-                value-format="YYYY-MM-DD HH:mm:ss" type="date" size="small" placeholder="閫夋嫨鏃ユ湡">
-              </el-date-picker>
-            </el-form-item>
-            <el-form-item label="璁惧绫诲瀷:">
-              <el-select v-model="editData.largeCategory" placeholder="璇烽�夋嫨" size="small" style="width:100%">
-                <el-option v-for="item in equipmentList" :key="item.value" :label="item.label" :value="item.value">
-                </el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item label="鍗曚环(涓囧厓):">
-              <el-input v-model="editData.unitPrice" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="褰撳墠鐘舵��:" prop="deviceStatus">
-              <el-select v-model="editData.deviceStatus" placeholder="璇烽�夋嫨" size="small" style="width:100%">
-                <el-option v-for="item in deviceStatusList" :key="item.value" :label="item.label" :value="item.value">
-                </el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item label="鏍″噯鍛ㄦ湡锛堟湀锛�:" prop="calibrationDate">
-              <el-input v-model="editData.calibrationDate" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="琚巿鏉冧汉:">
-              <el-select v-model="editData.authorizedPerson" multiple placeholder="璇烽�夋嫨" size="small" style="width:100%">
-                <el-option v-for="item in responsiblePersonList" :key="item.name" :label="item.name" :value="item.id">
-                </el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item label="鍥剧墖:">
-              <!-- <div
-                style="border: 1px solid #DCDFE6;border-radius:4px;height:32px;lineHeight:32px;display:flex;justify-content: space-around;font-size: 13px;">
-                <div v-show="Mdata.imageName" class="picName">{{ Mdata.imageName }}</div>
-                <el-upload :action="action" :on-success="handleSuccessUpImg2" :show-file-list="false"
-                  accept='image/jpg,image/jpeg,image/png' :headers="headers" :on-change="beforeUpload"
-                  :on-error="onError" ref='upload'>
-                  <el-button type="text" style="height:30px;padding-top:8px"><span v-if="Mdata.imageName"></span></el-button>
-                </el-upload>
-              </div> -->
-
-              <div>
-                <div v-show="editData.imageName" class="picName">{{ editData.imageName }}</div>
-                <el-upload :action="action" :on-success="handleSuccessUpImg2" :show-file-list="false"
-                  accept='image/jpg,image/jpeg,image/png' :headers="uploadHeader" :on-change="beforeUpload"
-                  :on-error="onError" ref='upload' class="avatar-uploader">
-                  <img v-if="editData.imageUpload" :src="javaApi + '/img/' + editData.imageUpload" class="avatar">
-                  <lims-icon name="el-icon-plus" v-else class="avatar-uploader-icon"></lims-icon>
-                </el-upload>
-              </div>
-            </el-form-item>
+            </div>
+            <div class="form-row">
+              <el-form-item label="浜у湴:">
+                <el-input v-model="editData.origin" size="small"></el-input>
+              </el-form-item>
+              <el-form-item label="鍑哄巶缂栧彿:">
+                <el-input v-model="editData.factoryNo" size="small"></el-input>
+              </el-form-item>
+            </div>
+            <div class="form-row">
+              <el-form-item label="璧勪骇缂栫爜:">
+                <el-input v-model="editData.assetCode" size="small"></el-input>
+              </el-form-item>
+              <el-form-item label="绠$悊缂栧彿:" prop="managementNumber">
+                <el-input v-model="editData.managementNumber" size="small"></el-input>
+              </el-form-item>
+            </div>
+            <div class="form-row">
+              <el-form-item label="璐疆鏃ユ湡:">
+                <el-date-picker style="width:100%" v-model="editData.acquisitionDate" type="date" format="YYYY-MM-DD"
+                  value-format="YYYY-MM-DD HH:mm:ss" size="small" placeholder="閫夋嫨鏃ユ湡">
+                </el-date-picker>
+              </el-form-item>
+              <el-form-item label="鏍″噯鏈夋晥鏈�:" prop="activationDate">
+                <el-date-picker style="width:100%" v-model="editData.activationDate" type="date" format="YYYY-MM-DD"
+                  value-format="YYYY-MM-DD HH:mm:ss" size="small" placeholder="閫夋嫨鏃ユ湡">
+                </el-date-picker>
+              </el-form-item>
+            </div>
+            <div class="form-row">
+              <el-form-item label="鏍″噯鏈嶅姟鏈烘瀯:">
+                <el-select v-model="editData.calibrationServices" clearable filterable size="small" style="width: 100%">
+                  <el-option v-for="name in calibrationServiceOptions" :key="name" :label="name" :value="name"></el-option>
+                </el-select>
+              </el-form-item>
+              <div style="flex: 1;"></div>
+            </div>
           </el-form>
         </el-col>
       </el-row>
+      <!-- 璁惧绠$悊 -->
+      <div class="section-title">璁惧绠$悊</div>
+      <el-form :model="editData" label-width="120px" ref="rules2" :rules="rules1">
+        <div class="form-row">
+          <el-form-item label="妫�娴嬮」鐩�:">
+            <el-cascader v-model="editData.insProductIds" :options="options" :show-all-levels="false" :props="props"
+              placeholder="璇烽�夋嫨" size="small" style="width:100%;" :collapse-tags="true" separator="," filterable
+              clearable></el-cascader>
+          </el-form-item>
+          <el-form-item label="璁惧绫诲瀷:">
+            <el-select v-model="editData.largeCategory" placeholder="璇烽�夋嫨" size="small" style="width:100%">
+              <el-option v-for="item in equipmentList" :key="item.value" :label="item.label" :value="item.value">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="鍗曚环(涓囧厓):">
+            <el-input v-model="editData.unitPrice" size="small"></el-input>
+          </el-form-item>
+        </div>
+        <div class="form-row">
+          <el-form-item label="褰撳墠鐘舵��:" prop="deviceStatus">
+            <el-select v-model="editData.deviceStatus" placeholder="璇烽�夋嫨" size="small" style="width:100%">
+              <el-option v-for="item in deviceStatusList" :key="item.value" :label="item.label" :value="item.value">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="璐熻矗浜�:">
+            <el-select v-model="editData.equipmentManager" placeholder="璇烽�夋嫨" size="small" style="width:100%">
+              <el-option v-for="item in responsiblePersonList" :key="item.name" :label="item.name" :value="item.id">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="琚巿鏉冧汉:">
+            <el-select v-model="editData.authorizedPerson" multiple placeholder="璇烽�夋嫨" size="small" style="width:100%">
+              <el-option v-for="item in inspectorList" :key="item.name" :label="item.name" :value="item.id">
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </div>
+        <div class="form-row">
+          <el-form-item label="瀛樻斁鐐�:">
+            <el-input v-model="editData.storagePoint" size="small"></el-input>
+          </el-form-item>
+          <div style="flex: 1;"></div>
+        </div>
+      </el-form>
+      <!-- 鏍″噯/淇濆吇/鏍告煡 鍛ㄦ湡淇℃伅 -->
+      <el-form :model="editData" :rules="rules1" ref="cycleForm" label-width="140px"
+        style="margin-top: 12px;border-top: 1px solid var(--lims-divider);padding-top: 4px;">
+        <div class="cycle-row">
+          <span class="cycle-title">鏍″噯淇℃伅</span>
+          <el-form-item label="鏈�杩戞牎鍑嗘棩鏈�:" class="cycle-item">
+            <el-date-picker style="width:100%" v-model="editData.lastCalibrationDate" format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD HH:mm:ss" type="date" size="small" placeholder="閫夋嫨鏃ユ湡">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="涓嬫鏍″噯鏃ユ湡:" class="cycle-item">
+            <el-date-picker style="width:100%" v-model="editData.nextCalibrationDate" format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD HH:mm:ss" type="date" size="small" placeholder="閫夋嫨鏃ユ湡">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="鏍″噯鍛ㄦ湡锛堟湀锛�:" prop="calibrationDate" class="cycle-item">
+            <el-input v-model="editData.calibrationDate" size="small"></el-input>
+          </el-form-item>
+        </div>
+        <div class="cycle-row">
+          <span class="cycle-title">淇濆吇淇℃伅</span>
+          <el-form-item label="鏈�杩戜繚鍏绘棩鏈�:" class="cycle-item">
+            <el-date-picker style="width:100%" v-model="editData.lastMaintenanceDate" @change="calcNextDate(editData)"
+              format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" type="date" size="small" placeholder="閫夋嫨鏃ユ湡">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="涓嬫淇濆吇鏃ユ湡:" class="cycle-item">
+            <el-date-picker :disabled="true" style="width:100%" v-model="editData.nextMaintenanceDate"
+              format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" type="date" size="small" placeholder="閫夋嫨鏃ユ湡">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="淇濆吇鍛ㄦ湡锛堟湀锛�:" class="cycle-item">
+            <el-input v-model="editData.maintenanceCycle" size="small" @change="calcNextDate(editData)"></el-input>
+          </el-form-item>
+        </div>
+        <div class="cycle-row">
+          <span class="cycle-title">鏍告煡淇℃伅</span>
+          <el-form-item label="鏈�杩戞牳鏌ユ棩鏈�:" class="cycle-item">
+            <el-date-picker style="width:100%" v-model="editData.lastExamineDate" @change="calcNextDate(editData)"
+              format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" type="date" size="small" placeholder="閫夋嫨鏃ユ湡">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="涓嬫鏍告煡鏃ユ湡:" class="cycle-item">
+            <el-date-picker :disabled="true" style="width:100%" v-model="editData.nextExamineDate"
+              format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" type="date" size="small" placeholder="閫夋嫨鏃ユ湡">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="鏍告煡鍛ㄦ湡锛堟湀锛�:" class="cycle-item">
+            <el-input v-model="editData.examineCycle" size="small" @change="calcNextDate(editData)"></el-input>
+          </el-form-item>
+        </div>
+      </el-form>
+      <!-- 鎶�鏈寚鏍� -->
+      <div class="section-title">鎶�鏈寚鏍�</div>
+      <el-form :model="editData" ref="ruleForm" :rules="rules1">
+        <el-form-item>
+          <el-input v-model="editData.technicalIndicators" :rows="7" type="textarea" size="small"></el-input>
+        </el-form-item>
+      </el-form>
+      </div>
       <template #footer><span  class="dialog-footer">
         <el-row>
           <el-button @click="handleClose">鍙� 娑�</el-button>
@@ -446,6 +485,7 @@
 
 <script>
 import { ElMessageBox } from 'element-plus'
+import dayjs from 'dayjs'
 import fileDownload from '@/utils/file'
 // vue-qr 鍙敮鎸� Vue2锛屾崲鎴愬悓 props 鐨勬湰鍦扮粍浠讹紙鍐呴儴鐢� Vue3 鐨� qrcode.vue锛�
 import vueQr from '@/components/QrCode'
@@ -463,10 +503,10 @@
   getInsProduction,
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
-import {
-  obtainItemParameterList,
-} from '@/api/cnas/resourceDemand/device.js'
+import { selectQualifiedSupplierManagementPage } from '@/api/cnas/externalService/supplierManage/supplierManage'
+import draftSave from '@/mixins/draftSave'
 export default {
+  mixins: [draftSave],
   props: {
     clickNodeVal: {
       type: Object,
@@ -499,9 +539,6 @@
         ],
         calibrationDate: [
           { required: true, message: '璇疯緭鍏ユ牎鍑嗗懆鏈�(鏈�)', trigger: 'blur' },
-        ],
-        subordinateDepartmentsId: [
-          { required: true, message: '璇烽�夋嫨鎵�灞為儴闂�', trigger: 'change' },
         ]
       },
       // dateForm: {
@@ -540,7 +577,7 @@
       dialogVisible: false,
       upLoad: false,
       responsiblePersonList: [],
-      subordinateDepartmentsList: [],
+      inspectorList: [],
       options: [],
       equipmentList: [],
       deviceStatusList: [],
@@ -553,9 +590,17 @@
       editData: {
         authorizedPerson: [],
       },
+      qualifiedSupplierNames: [],
     }
   },
   computed: {
+    // 鏍″噯鏈嶅姟鏈烘瀯涓嬫媺閫夐」锛堝悎鏍间緵搴斿晢 + 褰撳墠鍊煎厹搴曪級
+    calibrationServiceOptions() {
+      const list = this.qualifiedSupplierNames.slice();
+      const value = this.editData.calibrationServices;
+      if (value && list.indexOf(value) === -1) list.push(value);
+      return list;
+    },
     action() {
       return this.javaApi + '/deviceScope/uploadFile'
     }
@@ -566,8 +611,18 @@
     // 鑾峰彇鐩稿叧鏂囨。鐨勬暟鎹�
     this.getPage()
     this.timeStamp = Date.now()
+    this.obtainQualifiedSupplierList()
   },
   methods: {
+    // 鎷夊彇鍚堟牸渚涘簲鍟嗗垪琛紙鏍″噯鏈嶅姟鏈烘瀯涓嬫媺閫夐」锛�
+    obtainQualifiedSupplierList() {
+      selectQualifiedSupplierManagementPage({ current: 1, size: 999 }).then(res => {
+        if (res.code === 200) {
+          const rows = (res.data && res.data.records) || [];
+          this.qualifiedSupplierNames = [...new Set(rows.map(r => r.supplierName).filter(Boolean))];
+        }
+      });
+    },
     // 鍘熷厛鐨� Vue2 filter锛孷ue3 宸茬Щ闄� filters 閫夐」锛屾敼涓烘柟娉曡皟鐢�
     formaterDateTime(dateTime) {
       if (dateTime === undefined || dateTime === null || dateTime === '') {
@@ -602,8 +657,6 @@
     openFileRevisionDialog() {
       // 鑾峰彇妗f淇璐熻矗浜轰笅鎷夋鏁版嵁
       this.selectDevicePrincipal()
-      // 鑾峰彇妗f淇鎵�灞為儴闂ㄤ笅鎷夋鏁版嵁
-      this.obtainItemParameterList()
       // 鑾峰彇妗f淇璁惧鐘舵�佷笅鎷夋鏁版嵁
       this.selectEnumByCategory()
       // 鑾峰彇妗f淇妫�楠岄」鐩骇鑱斿脊妗嗘暟鎹�
@@ -631,6 +684,14 @@
         })
         this.fileList.push(obj)
       }
+      this.draftRestore('fileAdd', 'addFile', row.id, 'dialogVisible1')
+    },
+    // 鎵撳紑娣诲姞闄勪欢寮圭獥
+    openAddFileDia() {
+      this.dialogVisible1 = true
+      this.$nextTick(() => {
+        this.draftRestore('fileAdd', 'addFile', this.clickNodeVal.value, 'dialogVisible1')
+      })
     },
     handleDeleteClick(row) {
       // 鍒犻櫎閫昏緫
@@ -661,6 +722,7 @@
         updateDocument(this.addFile).then(res => {
           if (res.code == 200) {
             this.$message.success('鏇存柊鎴愬姛')
+            this.draftClear('fileAdd')
             this.dialogVisible1 = false;
             this.getPage()
           }
@@ -670,6 +732,7 @@
         addDocument(this.addFile).then(res => {
           if (res.code == 200) {
             this.$message.success('淇濆瓨鎴愬姛')
+            this.draftClear('fileAdd')
             this.dialogVisible1 = false;
             this.getPage()
           }
@@ -706,6 +769,27 @@
           this.tableDataA = res.data
       })
     },
+    // 琚巿鏉冧汉鍘嗗彶鍊煎彲鑳芥槸琚弽澶嶈浆涔夌殑澶氬眰 JSON 瀛楃涓诧紝閫愬眰瑙f瀽杩樺師鎴愭暟缁�
+    normalizeAuthorizedPerson(val) {
+      let v = val
+      for (let i = 0; i < 10; i++) {
+        if (typeof v !== 'string') break
+        if (v === '') {
+          v = []
+          break
+        }
+        try {
+          v = JSON.parse(v)
+        } catch (e) {
+          v = []
+          break
+        }
+      }
+      if (!Array.isArray(v)) {
+        v = v === '' || v === null || v === undefined ? [] : [v]
+      }
+      return v.filter(x => x !== '' && x !== null && x !== undefined)
+    },
     // 鏀堕泦鏁版嵁
     getList(id) {
       selectDeviceByCode({ id }).then(res => {
@@ -713,9 +797,7 @@
         if (res.code == 200) {
           this.Mdata = res.data;
           this.Mdata.insProductIds = this.Mdata.insProductIds.split(',')
-          if (this.Mdata.authorizedPerson) {
-            this.Mdata.authorizedPerson = JSON.parse(this.Mdata.authorizedPerson)
-          }
+          this.Mdata.authorizedPerson = this.normalizeAuthorizedPerson(this.Mdata.authorizedPerson)
         }
       });
     },
@@ -734,7 +816,32 @@
       this.editData = JSON.parse(JSON.stringify(this.Mdata))
       this.$nextTick(() => {
         this.dialogVisible = true
+        this.draftRestore('fileRevision', 'editData', this.clickNodeVal.value, 'dialogVisible')
       })
+    },
+    // 涓嬫鏃ユ湡 = 鏈�杩戞棩鏈� + 鍛ㄦ湡锛堟湀锛夛紝鑷姩璁$畻
+    calcNextDate(data) {
+      const calc = (lastDate, cycle) => {
+        const period = parseInt(cycle)
+        if (!lastDate || !period || period <= 0) {
+          return null
+        }
+        return dayjs(String(lastDate).replace(' ', 'T'))
+          .add(period, 'month')
+          .format('YYYY-MM-DD HH:mm:ss')
+      }
+      const nextCalibrationDate = calc(data.lastCalibrationDate, data.calibrationDate)
+      if (nextCalibrationDate) {
+        data.nextCalibrationDate = nextCalibrationDate
+      }
+      const nextMaintenanceDate = calc(data.lastMaintenanceDate, data.maintenanceCycle)
+      if (nextMaintenanceDate) {
+        data.nextMaintenanceDate = nextMaintenanceDate
+      }
+      const nextExamineDate = calc(data.lastExamineDate, data.examineCycle)
+      if (nextExamineDate) {
+        data.nextExamineDate = nextExamineDate
+      }
     },
     //淇妗f
     submitForm() {
@@ -757,6 +864,12 @@
           return false;
         }
       });
+      this.$refs['cycleForm'].validate((valid) => {
+        if (!valid) {
+          flag = false;
+          return false;
+        }
+      });
       if (!flag) {
         return;
       }
@@ -768,15 +881,14 @@
       const formData = this.HaveJson(this.editData)
       formData.userAllow = this.equipmentManager.toString();
       formData.insProductIds = Array.isArray(formData.insProductIds) ? formData.insProductIds.join(',') : '';
-      if (formData.authorizedPerson.length === 0) {
-        formData.authorizedPerson = ''
-      } else {
-        formData.authorizedPerson = JSON.stringify(formData.authorizedPerson)
-      }
+      formData.authorizedPerson = Array.isArray(formData.authorizedPerson) && formData.authorizedPerson.length
+        ? JSON.stringify(formData.authorizedPerson)
+        : ''
       this.upLoad = true;
       upDeviceParameter(formData).then(res => {
         this.$message.success('淇敼鎴愬姛')
         this.upLoad = false
+        this.draftClear('fileRevision')
         this.getList(this.clickNodeVal.value)
         this.dialogVisible = false
       }).catch(e => {
@@ -822,17 +934,9 @@
       selectUserCondition().then(res => {
         this.responsiblePersonList = res.data;
       })
-    },
-    obtainItemParameterList() {
-      obtainItemParameterList().then(res => {
-        let data = []
-        res.data.forEach(a => {
-          data.push({
-            label: a.laboratoryName,
-            value: a.id
-          })
-        })
-        this.subordinateDepartmentsList = data
+      // 琚巿鏉冧汉涓嬫媺鍙彇妫�娴嬪憳瑙掕壊浜哄憳
+      selectUserCondition({ type: 3 }).then(res => {
+        this.inspectorList = res.data;
       })
     },
     getInsProductIds() {
@@ -887,6 +991,7 @@
     },
     dialogVisible1(newVal) {
       if (newVal == false) {
+        this.draftStop('fileAdd')
         this.isAddFileUpdate = false
         this.addFile = {}
         this.fileList = []
@@ -928,6 +1033,57 @@
 
 .tables {
   width: 100%;
+}
+
+.cycle-row {
+  display: flex;
+  align-items: center;
+}
+
+.cycle-title {
+  width: 68px;
+  flex-shrink: 0;
+  font-size: 13px;
+  color: var(--lims-text-2, #909399);
+}
+
+.cycle-item {
+  flex: 1;
+  margin-bottom: 6px;
+  margin-right: 10px;
+}
+
+.cycle-item:last-child {
+  margin-right: 0;
+}
+
+.form-row {
+  display: flex;
+  gap: 16px;
+}
+
+.form-row > .el-form-item {
+  flex: 1;
+}
+
+.section-title {
+  position: relative;
+  padding-left: 10px;
+  margin: 14px 0 12px;
+  font-size: 13px;
+  font-weight: 600;
+  color: var(--lims-text-1, #303133);
+}
+
+.section-title::before {
+  content: "";
+  position: absolute;
+  left: 0;
+  top: 3px;
+  bottom: 3px;
+  width: 3px;
+  border-radius: 2px;
+  background: var(--el-color-primary, #409eff);
 }
 
 .el-image {
@@ -976,7 +1132,7 @@
   display: inline-block;
   text-align: right;
   margin-right: 20px;
-  color: #999;
+  color: var(--lims-text-3);
 }
 
 .form-item p {

--
Gitblit v1.9.3