From c6e96cdb8b1cfb51e9a45bf86c38d1353e983127 Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期一, 19 十月 2026 15:19:48 +0800
Subject: [PATCH] 设备模块业务完善及前序页面优化

---
 src/api/cnas/resourceDemand/device.js                                                                 |   63 
 src/views/CNAS/resourceDemand/device/component/quantityValueTraceabilityPlan.vue                      |   10 
 src/views/CNAS/resourceDemand/device/index.vue                                                        |   18 
 src/views/CNAS/resourceDemand/device/component/files.vue                                              |  202 +-
 src/views/CNAS/resourceDemand/device/component/management.vue                                         |   64 
 src/views/CNAS/resourceDemand/device/component/state.vue                                              |  109 
 src/views/CNAS/resourceDemand/device/component/inspectionForm.vue                                     |    5 
 src/views/CNAS/resourceDemand/device/component/dateFormat.js                                          |   26 
 src/views/CNAS/resourceDemand/device/component/equipmentAcceptance.vue                                |   31 
 src/views/CNAS/resourceDemand/device/component/usingExternalInstruments.vue                           |   12 
 src/views/CNAS/resourceDemand/standardMaterial/index.vue                                              |   10 
 src/views/CNAS/resourceDemand/device/component/calibration.vue                                        |  376 ----
 src/views/CNAS/resourceDemand/device/component/equipmentCheck.vue                                     |   67 
 src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue                           |  730 +++++----
 src/views/CNAS/resourceDemand/device/component/equipmentCalibrationPlan.vue                           |  623 +++----
 src/views/CNAS/resourceDemand/facilitiesEnvironment/component/facilities-environmental-conditions.vue |   22 
 src/views/CNAS/resourceDemand/device/component/accidentForm.vue                                       |   31 
 src/views/CNAS/resourceDemand/device/component/fault.vue                                              |    7 
 src/views/CNAS/resourceDemand/device/component/checkRecord.vue                                        |   40 
 src/views/CNAS/resourceDemand/device/component/inspectionOfEquipment.vue                              |   11 
 src/views/CNAS/resourceDemand/device/component/calibrationRecordDia.vue                               |  448 +++++
 src/views/CNAS/process/nonconformingWork/nonconformingDistribution/index.vue                          |    7 
 src/views/CNAS/resourceDemand/device/component/applicationForm.vue                                    |   30 
 src/views/CNAS/resourceDemand/device/component/equipmentScrap.vue                                     |   16 
 src/views/CNAS/resourceDemand/device/component/check.vue                                              |   15 
 src/views/CNAS/resourceDemand/device/component/equipmentFailure.vue                                   |   12 
 src/views/CNAS/resourceDemand/device/component/addYearPlanDia.vue                                     |   26 
 src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue                                 |   40 
 src/utils/saveBlob.js                                                                                 |   30 
 src/views/CNAS/resourceDemand/device/component/scrapApplicationForm.vue                               |   30 
 src/views/CNAS/resourceDemand/device/component/borrow.vue                                             |   76 
 /dev/null                                                                                             |  285 ---
 src/views/CNAS/resourceDemand/device/component/operationInstruction.vue                               |   86 
 src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue                               |   36 
 src/views/CNAS/resourceDemand/device/component/deviceOverview.vue                                     |   21 
 src/views/CNAS/resourceDemand/device/component/record.vue                                             |   39 
 src/views/CNAS/process/method/standardNoveltyRetrieval/component/FormDialog.vue                       |  148 +
 src/views/CNAS/resourceDemand/device/component/failureForm.vue                                        |   24 
 src/views/CNAS/resourceDemand/device/component/acceptanceForm.vue                                     |    1 
 src/views/CNAS/resourceDemand/device/component/equipmentAccident.vue                                  |   17 
 src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue                          |  665 +++----
 41 files changed, 2,421 insertions(+), 2,088 deletions(-)

diff --git a/src/api/cnas/resourceDemand/device.js b/src/api/cnas/resourceDemand/device.js
index 74e1f1e..f72c9df 100644
--- a/src/api/cnas/resourceDemand/device.js
+++ b/src/api/cnas/resourceDemand/device.js
@@ -152,6 +152,15 @@
   });
 }
 
+// 鎸夊勾浠芥煡璇㈣澶囨牎鍑嗚鍒掞紙涓嶅瓨鍦ㄥ垯鑷姩鍒涘缓锛屽苟鑷姩琛ュ叏鍒扮偣鏄庣粏锛�
+export function getCalibrationPlanByYear(query) {
+  return request({
+    url: "/deviceCalibrationPlan/getPlanByYear",
+    method: "get",
+    params: query,
+  });
+}
+
 // 鎻愪氦鎵瑰噯閫氱煡
 export function submiatRatifyDeviceCalibrationPlan(data) {
   return request({
@@ -310,6 +319,15 @@
 export function pageDeviceExaminePlan(query) {
   return request({
     url: "/deviceExaminePlan/pageDeviceExaminePlan",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鎸夊勾浠芥煡璇㈣澶囨牳鏌ヨ鍒掞紙涓嶅瓨鍦ㄥ垯鑷姩鍒涘缓锛屽苟鑷姩琛ュ叏鍒扮偣鏄庣粏锛�
+export function getExaminePlanByYear(query) {
+  return request({
+    url: "/deviceExaminePlan/getPlanByYear",
     method: "get",
     params: query,
   });
@@ -517,6 +535,51 @@
   });
 }
 
+// 鎸夊勾浠芥煡璇㈣澶囦繚鍏昏鍒掞紙涓嶅瓨鍦ㄥ垯鑷姩鍒涘缓锛屽苟鑷姩琛ュ叏鍒扮偣鏄庣粏锛�
+export function getMaintenancePlanByYear(query) {
+  return request({
+    url: "/deviceMaintenancePlan/getPlanByYear",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鍒嗛〉鏌ヨ璁惧淇濆吇璁″垝璇︽儏
+export function pageMaintenancePlanDetail(query) {
+  return request({
+    url: "/deviceMaintenancePlan/pageMaintenancePlanDetail",
+    method: "get",
+    params: query,
+  });
+}
+
+// 淇敼璁惧淇濆吇璁″垝璇︽儏
+export function updateMaintenancePlanDetail(data) {
+  return request({
+    url: "/deviceMaintenancePlan/updateMaintenancePlanDetail",
+    method: "post",
+    data: data,
+  });
+}
+
+// 鍒犻櫎璁惧淇濆吇璁″垝璇︽儏
+export function deleteMaintenancePlanDetail(query) {
+  return request({
+    url: "/deviceMaintenancePlan/delMaintenancePlanDetail",
+    method: "delete",
+    params: query,
+  });
+}
+
+// 瀹℃牳璁惧淇濆吇璁″垝
+export function reviewMaintenancePlanStatus(data) {
+  return request({
+    url: "/deviceMaintenancePlan/reviewMaintenancePlanStatus",
+    method: "post",
+    data: data,
+  });
+}
+
 //鍒嗛〉鏌ヨ閲忓�兼函婧愯鍒�
 export function selectDeviceTraceabilityManagementByPage(query) {
   return request({
diff --git a/src/utils/saveBlob.js b/src/utils/saveBlob.js
new file mode 100644
index 0000000..0685d7a
--- /dev/null
+++ b/src/utils/saveBlob.js
@@ -0,0 +1,30 @@
+import { ElMessage } from 'element-plus'
+import { saveAs } from 'file-saver'
+
+/**
+ * 淇濆瓨鎺ュ彛杩斿洖鐨勪簩杩涘埗鏂囦欢锛涜嫢鍚庣瀹為檯杩斿洖鐨勬槸閿欒 JSON锛屽垯鎻愮ず閿欒鑰屼笉鏄瓨鎴愬潖鏂囦欢銆�
+ * @param {Blob} data 璇锋眰杩斿洖鐨� blob
+ * @param {string} filename 涓嬭浇鏂囦欢鍚�
+ * @param {string} mime 鏂囦欢绫诲瀷
+ */
+export function saveBlobOrShowError(data, filename, mime = 'application/octet-stream') {
+  const reader = new FileReader()
+  reader.readAsText(data, 'utf-8')
+  reader.onload = () => {
+    const text = (reader.result || '').trim()
+    if (text.startsWith('{') || text.startsWith('[')) {
+      let msg = '瀵煎嚭澶辫触'
+      try {
+        msg = JSON.parse(text).msg || msg
+      } catch (e) {
+        // 闈炴爣鍑嗛敊璇粨鏋勶紝淇濈暀榛樿鎻愮ず
+      }
+      ElMessage.error(msg)
+    } else {
+      saveAs(new Blob([data], { type: mime }), filename)
+    }
+  }
+  reader.onerror = () => {
+    saveAs(new Blob([data], { type: mime }), filename)
+  }
+}
diff --git a/src/views/CNAS/process/method/standardNoveltyRetrieval/component/FormDialog.vue b/src/views/CNAS/process/method/standardNoveltyRetrieval/component/FormDialog.vue
index 1f92114..e339fe4 100644
--- a/src/views/CNAS/process/method/standardNoveltyRetrieval/component/FormDialog.vue
+++ b/src/views/CNAS/process/method/standardNoveltyRetrieval/component/FormDialog.vue
@@ -1,47 +1,51 @@
 <template>
   <div>
-    <el-dialog v-model="formDia" title="鏂板" width="80%" @close="closeDia">
-      <el-form ref="form" :model="form" :rules="formRules" label-width="auto">
-        <el-button size="small" type="primary" @click="addBtn">娣诲姞涓�鏉�</el-button>
+    <el-dialog v-model="formDia" title="鏂板" width="800px" @close="closeDia">
+      <el-form ref="form" :model="form" :rules="formRules" label-width="120px">
         <div class="form-info">
-          <div v-for="(items,index) in form.taskRel" :key="index">
-            <el-col :span="12">
-              <el-form-item :prop="`taskRel.${index}.newMethodName`" :rules="{required: true, message: '璇峰~鍐欐爣鍑嗗悕绉�',trigger: 'blur',}" label="鏂版爣鍑嗗悕绉帮細">
-                <el-input v-model="items.newMethodName" size="small"></el-input>
-              </el-form-item>
-            </el-col>
-            <el-col :span="12">
-              <el-form-item :prop="`taskRel.${index}.newStandardNo`" :rules="{required: true,message: '璇峰~鍐欐爣鍑嗗彿',trigger: 'blur',}" label="鏂版爣鍑嗗彿锛�">
-                <el-input v-model="items.newStandardNo" size="small"></el-input>
-              </el-form-item>
-            </el-col>
-            <el-col :span="12">
-              <el-form-item :prop="`taskRel.${index}.searchNewSource`" :rules="{required: true,message: '璇烽�夋嫨鏌ユ柊璁板綍鏉ユ簮',trigger: 'change',}" label="鏌ユ柊璁板綍鏉ユ簮锛�">
-                <el-radio-group v-model="items.searchNewSource">
-                  <el-radio :value="0">鏍囧噯缃�</el-radio>
-                  <el-radio :value="1">濮旀墭鎯呮姤</el-radio>
-                  <el-radio :value="2">鏍囧噯鏁�</el-radio>
-                  <el-radio :value="3">鍏朵粬</el-radio>
-                </el-radio-group>
-              </el-form-item>
-            </el-col>
-            <el-col :span="8">
-              <el-form-item :prop="`taskRel.${index}.remark`" :rules="{required: false,message: '璇烽�夋嫨澶囨敞',trigger: 'change',}" label="澶囨敞锛�">
-                <el-select v-model="items.remark" :prop="`taskRel.${index}.remark`"
-                           :rules="{required: false,message: '璇烽�夋嫨澶囨敞',trigger: 'change',}"
-                           clearable size="small">
-                  <el-option :value="0" label="浣滃簾"></el-option>
-                  <el-option :value="1" label="鏇挎崲"></el-option>
-                </el-select>
-              </el-form-item>
-            </el-col>
-            <el-col :span="4">
-              <el-button v-if="index !== 0" circle :icon="$icon('el-icon-delete')" size="small" type="danger" @click="deleteHeaderRow(index)"></el-button>
-            </el-col>
-            <el-col :span="24">
-              <el-divider></el-divider>
-            </el-col>
+          <div v-for="(items,index) in form.taskRel" :key="index" class="record-block">
+            <div class="record-head">
+              <span class="record-title">
+                <span class="record-index">{{ index + 1 }}</span>
+                鏌ユ柊璁板綍
+              </span>
+              <el-button v-if="index !== 0" link type="danger" :icon="$icon('el-icon-delete')"
+                @click="deleteHeaderRow(index)">鍒犻櫎鏈潯</el-button>
+            </div>
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item :prop="`taskRel.${index}.newMethodName`" :rules="{required: true, message: '璇峰~鍐欐爣鍑嗗悕绉�',trigger: 'blur',}" label="鏂版爣鍑嗗悕绉帮細">
+                  <el-input v-model="items.newMethodName" size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item :prop="`taskRel.${index}.newStandardNo`" :rules="{required: true,message: '璇峰~鍐欐爣鍑嗗彿',trigger: 'blur',}" label="鏂版爣鍑嗗彿锛�">
+                  <el-input v-model="items.newStandardNo" size="small"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="24">
+                <el-form-item :prop="`taskRel.${index}.searchNewSource`" :rules="{required: true,message: '璇烽�夋嫨鏌ユ柊璁板綍鏉ユ簮',trigger: 'change',}" label="鏌ユ柊璁板綍鏉ユ簮锛�">
+                  <el-radio-group v-model="items.searchNewSource">
+                    <el-radio :value="0">鏍囧噯缃�</el-radio>
+                    <el-radio :value="1">濮旀墭鎯呮姤</el-radio>
+                    <el-radio :value="2">鏍囧噯鏁�</el-radio>
+                    <el-radio :value="3">鍏朵粬</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item :prop="`taskRel.${index}.remark`" :rules="{required: false,message: '璇烽�夋嫨澶囨敞',trigger: 'change',}" label="澶囨敞锛�">
+                  <el-select v-model="items.remark" clearable size="small" style="width: 100%;">
+                    <el-option :value="0" label="浣滃簾"></el-option>
+                    <el-option :value="1" label="鏇挎崲"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
           </div>
+        </div>
+        <div class="add-btn-wrap">
+          <el-button class="add-btn" @click="addBtn">娣诲姞涓�鏉�</el-button>
         </div>
       </el-form>
       <template #footer><span  class="dialog-footer">
@@ -120,10 +124,70 @@
 
 <style scoped>
 .form-info {
-  display: inline-block;
-  max-height: 42em;
+  max-height: 52vh;
   overflow-y: auto;
+  padding-right: 4px;
 }
+
+.record-block {
+  background: #fafafa;
+  border: 1px solid #ebeef5;
+  border-radius: 6px;
+  padding: 14px 16px 0;
+  margin-bottom: 14px;
+}
+
+.record-head {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding-bottom: 10px;
+  margin-bottom: 14px;
+  border-bottom: 1px dashed #e4e7ed;
+}
+
+.record-title {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  font-size: 14px;
+  font-weight: 600;
+  color: var(--el-text-color-primary);
+}
+
+.record-index {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  width: 20px;
+  height: 20px;
+  border-radius: 50%;
+  background: var(--el-color-primary);
+  color: #fff;
+  font-size: 12px;
+}
+
+.add-btn-wrap {
+  margin-top: 4px;
+}
+
+.add-btn {
+  width: 100%;
+  color: var(--el-color-primary);
+  border: 1px dashed var(--el-color-primary);
+  background: transparent;
+}
+
+.add-btn:hover {
+  color: var(--el-color-primary);
+  border-color: var(--el-color-primary);
+  background: var(--el-color-primary-light-9);
+}
+
+:deep(.record-block .el-form-item) {
+  margin-bottom: 16px;
+}
+
 :deep(.el-dialog) {
   margin: 6vh auto 50px !important;
 }
diff --git a/src/views/CNAS/process/nonconformingWork/nonconformingDistribution/index.vue b/src/views/CNAS/process/nonconformingWork/nonconformingDistribution/index.vue
index 73c519c..47474d4 100644
--- a/src/views/CNAS/process/nonconformingWork/nonconformingDistribution/index.vue
+++ b/src/views/CNAS/process/nonconformingWork/nonconformingDistribution/index.vue
@@ -42,6 +42,7 @@
   delInconsistentDistribution,
   exportInconsistentDistribution,
 } from '@/api/cnas/process/nonconformingWork.js'
+import { formatListDate } from '@/views/CNAS/resourceDemand/device/component/dateFormat'
 
 export default {
   name: 'NonconformingDistribution',
@@ -67,7 +68,8 @@
         {
           label: '鍒涘缓鏃堕棿',
           prop: 'createTime',
-          minWidth: '100'
+          minWidth: '150',
+          formatData: val => formatListDate(val)
         },
         {
           label: '淇敼浜�',
@@ -77,7 +79,8 @@
         {
           label: '淇敼鏃堕棿',
           prop: 'updateTime',
-          minWidth: '100'
+          minWidth: '150',
+          formatData: val => formatListDate(val)
         },
         {
           dataType: 'action',
diff --git a/src/views/CNAS/resourceDemand/device/component/acceptanceForm.vue b/src/views/CNAS/resourceDemand/device/component/acceptanceForm.vue
index 331d207..813733b 100644
--- a/src/views/CNAS/resourceDemand/device/component/acceptanceForm.vue
+++ b/src/views/CNAS/resourceDemand/device/component/acceptanceForm.vue
@@ -138,6 +138,7 @@
     submitForm() {
       this.$refs.modelForm.validate((valid) => {
         if (valid) {
+          this.submitFormLoading = true
           if (this.operationType === 'add') {
             addDeviceAcceptance(this.form).then(res => {
               if (res.code == 200) {
diff --git a/src/views/CNAS/resourceDemand/device/component/accidentForm.vue b/src/views/CNAS/resourceDemand/device/component/accidentForm.vue
index a6d4ebc..74524d7 100644
--- a/src/views/CNAS/resourceDemand/device/component/accidentForm.vue
+++ b/src/views/CNAS/resourceDemand/device/component/accidentForm.vue
@@ -9,7 +9,7 @@
         <el-step title="鎶�鏈礋璐d汉鎰忚" @click="setStep(3)"></el-step>
         <el-step title="涓讳换鎰忚" @click="setStep(4)"></el-step>
       </el-steps>
-      <el-form ref="modelForm" :model="form" :rules="rules" label-width="160px">
+      <el-form ref="modelForm" :model="form" :rules="rules" label-width="160px" :disabled="!canOperate">
         <el-col v-if="showStep === 0" :span="12">
           <el-form-item label="鍦扮偣锛�" prop="address">
             <el-input v-model="form.address" :disabled="currentStep !== 0" clearable size="small"></el-input>
@@ -87,7 +87,7 @@
       </el-form>
       <template #footer><span  class="dialog-footer">
         <el-button @click="resetForm">鍙� 娑�</el-button>
-        <el-button v-if="currentStep !== 5" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
+        <el-button v-if="currentStep !== 5 && canOperate" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
           璁�</el-button>
       </span></template>
     </el-dialog>
@@ -96,6 +96,7 @@
 
 <script>
 import { selectUserCondition } from "@/api/business/inspectionTask";
+import { mapGetters } from "@/utils/store-compat";
 import {
   getDeviceAccidentReport,
   addDeviceAccidentReport,
@@ -109,6 +110,7 @@
     return {
       dialogVisible: false,
       submitFormLoading: false,
+      canOperate: true,
       form: {
         accidentReportId: '',
         address: '',
@@ -145,6 +147,7 @@
     // 鎵撳紑寮规
     openDialog(id, deviceId) {
       this.dialogVisible = true
+      this.canOperate = true
       this.form.accidentReportId = id
       this.form.deviceId = deviceId
       this.getUserList()
@@ -178,10 +181,30 @@
             this.currentStep = 5
             this.showStep = 4
           }
+          this.applyPermission()
         }
       }).catch(error => {
         console.error(error)
       })
+    },
+    // 闈炲綋鍓嶇幆鑺傝矗浠讳汉鍙厑璁告煡鐪�
+    applyPermission() {
+      if (this.form.isFinish === 1 || this.currentStep >= 5) {
+        this.canOperate = false
+        return
+      }
+      const responsibleList = [
+        this.form.reportUser,
+        this.form.assessorUser,
+        this.form.departmentHeadUser,
+        this.form.technicalDirectorUser,
+        this.form.directorHeadUser,
+      ]
+      const responsible = responsibleList[this.currentStep]
+      this.canOperate = !responsible || responsible === this.nickName
+      if (!this.canOperate) {
+        this.$message.warning('褰撳墠鐜妭璐d换浜轰负锛�' + responsible + '锛屾偍鍙兘鏌ョ湅')
+      }
     },
     setStep(step) {
       this.showStep = step
@@ -191,6 +214,7 @@
       this.form.flowType = this.currentStep
       this.$refs.modelForm.validate((valid) => {
         if (valid) {
+          this.submitFormLoading = true
           addDeviceAccidentReport(this.form).then(res => {
             if (res.code == 200) {
               this.$message.success('鏂板鎴愬姛')
@@ -214,6 +238,9 @@
       })
     },
   },
+  computed: {
+    ...mapGetters(["nickName"]),
+  },
 }
 </script>
 
diff --git a/src/views/CNAS/resourceDemand/device/component/addVerificationYearPlanDia.vue b/src/views/CNAS/resourceDemand/device/component/addVerificationYearPlanDia.vue
deleted file mode 100644
index c367d6a..0000000
--- a/src/views/CNAS/resourceDemand/device/component/addVerificationYearPlanDia.vue
+++ /dev/null
@@ -1,285 +0,0 @@
-<template>
-  <div>
-    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="applicationForm"
-      title="娣诲姞璁惧鏍告煡璁″垝" width="80%" @close="closeDialog">
-      <div style="display: flex;align-items: center;">
-        <el-button style="margin-right: 10px" size="small" type="primary" @click="addTableRow">娣诲姞</el-button>
-        <span style="width: 80px">璁″垝鍚嶇О锛�</span>
-        <el-input style="width: 300px;margin-right: 10px" v-model="form.planName" clearable size="small"></el-input>
-        <span style="width: 60px">骞翠唤锛�</span>
-        <el-date-picker v-model="form.planYear" type="year" value-format="YYYY" clearable size="small" format="YYYY"
-          placeholder="閫夋嫨骞�">
-        </el-date-picker>
-      </div>
-      <div style="margin: 10px 0">
-        <el-table ref="yearTable" :data="examinePlanDetailsList" id="templateParamTable" row-key="deviceId"
-                  v-loading="yearTableLoading"
- border height="560px">
-          <el-table-column label="璁惧鍚嶇О" min-width="190" prop="deviceName">
-            <template #default="scope">
-              <el-input v-model="scope.row.deviceName" clearable size="small"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="璁惧缂栧彿" min-width="190" prop="deviceNumber">
-            <template #default="scope">
-              <el-input v-model="scope.row.deviceNumber" clearable size="small"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="鏍告煡鏃堕棿" min-width="170" prop="checkTime">
-            <template #default="scope">
-              <el-date-picker v-model="scope.row.checkTime" clearable format="YYYY-MM" placeholder="閫夋嫨鏃ユ湡" size="small"
-                style="width:100%" type="month" value-format="YYYY-MM">
-              </el-date-picker>
-            </template>
-          </el-table-column>
-          <el-table-column label="鏍告煡鎸囨爣" min-width="120" prop="checkIndex">
-            <template #default="scope">
-              <el-input v-model="scope.row.checkIndex" clearable size="small"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="鏍告煡鏂规硶" min-width="150" prop="checkMethod">
-            <template #default="scope">
-              <el-input v-model="scope.row.checkMethod" clearable size="small" type="textarea"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="缁撴灉濡備綍鍒ゅ畾" min-width="150" prop="howResults">
-            <template #default="scope">
-              <el-input v-model="scope.row.howResults" clearable size="small" type="textarea"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="鏍告煡璐d换浜�" min-width="170" prop="checkChargerUserId">
-            <template #default="scope">
-              <el-select v-model="scope.row.checkChargerUserId" placeholder="璇烽�夋嫨" size="small" style="width: 100%"
-                @change="setCheckChargerUser(scope.row.checkChargerUserId, scope.row)">
-                <el-option v-for="item in userList" :key="item.value" :label="item.label"
-                  :value="item.value"></el-option>
-              </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="澶囨敞" min-width="170" prop="remark">
-            <template #default="scope">
-              <el-input v-model="scope.row.remark" clearable size="small"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column fixed="right" label="鎿嶄綔" width="80" align="center">
-            <template #default="scope">
-              <el-button link type="danger" @click="deleteRow(scope.$index)">鍒犻櫎</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-      </div>
-      <template #footer><span  class="dialog-footer">
-        <el-button @click="closeDialog">鍙� 娑�</el-button>
-        <el-button :loading="submitFormLoading" type="primary" @click="submitForm">纭� 璁�</el-button>
-      </span></template>
-    </el-dialog>
-    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="addEquipDia" title="鏂板骞村害璁″垝"
-      width="50%">
-      <el-table ref="multipleTable" :data="equipOptions" tooltip-effect="dark" height="500" style="width: 100%"
- border
-        @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55"></el-table-column>
-        <el-table-column label="璁惧鍚嶇О" prop="label"></el-table-column>
-        <el-table-column prop="value" label="璁惧缂栧彿"></el-table-column>
-      </el-table>
-      <template #footer><span  class="dialog-footer">
-        <el-button @click="addEquipDia = false">鍙� 娑�</el-button>
-        <el-button :loading="submitFormLoading" type="primary" @click="changeMachineName">纭� 璁�</el-button>
-      </span></template>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import Sortable from "sortablejs";
-import {
-  getDeviceExaminePlan,
-  addDeviceExaminePlan,
-  updateDeviceExaminePlan,
-  deviceScopeSearch,
-} from '@/api/cnas/resourceDemand/device.js'
-import { selectUserCondition } from "@/api/performance/class";
-import draftSave from '@/mixins/draftSave'
-export default {
-  name: "addVerificationYearPlanDia",
-  // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
-  components: {},
-  mixins: [draftSave],
-  data() {
-    // 杩欓噷瀛樻斁鏁版嵁
-    return {
-      applicationForm: false,
-      addEquipDia: false,
-      submitFormLoading: false,
-      equipOptions: [],
-      examinePlanDetailsList: [],
-      selectionRows: [],
-      userList: [],
-      form: {
-        planName: '',
-        planYear: '',
-        planId: '',
-        examinePlanDetailsList: [],
-      },
-      operationType: '',
-      yearTableLoading: false
-    }
-  },
-  mounted() {
-
-  },
-  // 鏂规硶闆嗗悎
-  methods: {
-    openDialog(type, row) {
-      this.operationType = type
-      if (type === 'add') {
-        this.form = {
-          planName: '',
-          planYear: '',
-          examinePlanDetailsList: [],
-        }
-        this.examinePlanDetailsList = []
-        this.$nextTick(() => {
-          this.draftRestore('addVerificationYearPlanDiaForm', 'form', '', 'applicationForm')
-          this.draftRestore('addVerificationYearPlanDiaRows', 'examinePlanDetailsList', '', 'applicationForm')
-        })
-      } else {
-        this.getRowInfo(row)
-      }
-      this.applicationForm = true
-      this.getUserList()
-    },
-    getRowInfo(row) {
-      this.yearTableLoading = true
-      getDeviceExaminePlan({ planId: row.planId }).then(res => {
-        this.yearTableLoading = false
-        if (res.code == 200) {
-          this.examinePlanDetailsList = res.data.examinePlanDetailsList
-          this.form.planName = res.data.planName
-          this.form.planYear = res.data.planYear
-          this.form.planId = res.data.planId
-          this.$nextTick(() => {
-            this.draftRestore('addVerificationYearPlanDiaForm', 'form', this.form.planId, 'applicationForm')
-            this.draftRestore('addVerificationYearPlanDiaRows', 'examinePlanDetailsList', this.form.planId, 'applicationForm')
-          })
-        }
-      }).catch(error => {
-        this.yearTableLoading = false
-      })
-    },
-    // 娣诲姞璁惧
-    addTableRow() {
-      this.addEquipDia = true
-      this.getEquipOptions()
-    },
-    handleSelectionChange(selection) {
-      this.selectionRows = selection
-    },
-    setCheckChargerUser(id, row) {
-      const index = this.userList.findIndex(item => item.id === id)
-      if (index > -1) {
-        row.checkChargerUser = this.userList[index].name
-      }
-    },
-    changeMachineName() {
-      this.selectionRows.map(val => {
-        this.examinePlanDetailsList.push({ deviceId: val.id, deviceName: val.label, deviceNumber: val.value, specificationModel: val.specificationModel })
-      })
-      this.addEquipDia = false
-      this.rowDrop()
-    },
-    rowDrop() {
-      const that = this
-      const tbody = document.querySelector(
-        '#templateParamTable .el-table__body-wrapper tbody'
-      )
-      if (!this.sortTable) {
-        this.sortTable = Sortable.create(tbody, {
-          animation: 200, //鍔ㄧ敾鏃堕暱
-          handle: ".el-table__row", //鍙嫋鎷藉尯鍩焎lass
-          //鎷栨嫿涓簨浠�
-          onMove: ({ dragged, related }) => {
-            const oldRow = that.examinePlanDetailsList[dragged.rowIndex] //鏃т綅缃暟鎹�
-            const newRow = that.examinePlanDetailsList[related.rowIndex] //琚嫋鎷界殑鏂版暟鎹�
-          },
-          //鎷栨嫿缁撴潫浜嬩欢
-          onEnd: evt => {
-            const curRow = that.examinePlanDetailsList.splice(evt.oldIndex, 1)[0];
-            that.examinePlanDetailsList.splice(evt.newIndex, 0, curRow);
-          }
-        })
-      }
-    },
-    // 鍒犻櫎琛ㄦ牸琛�
-    deleteRow(index) {
-      this.examinePlanDetailsList.splice(index, 1)
-    },
-    // 鎻愪氦鏂板
-    submitForm() {
-      this.form.examinePlanDetailsList = this.HaveJson(this.examinePlanDetailsList)
-      this.submitFormLoading = true
-      if (this.operationType === 'add') {
-        addDeviceExaminePlan(this.form).then(res => {
-          if (res.code == 200) {
-            this.$message.success('鏂板鎴愬姛')
-            this.draftClear('addVerificationYearPlanDiaForm')
-            this.draftClear('addVerificationYearPlanDiaRows')
-            this.closeDialog()
-            this.$emit('closeDia')
-          }
-          this.submitFormLoading = false
-        }).catch(err => {
-          this.submitFormLoading = false
-        })
-      } else {
-        updateDeviceExaminePlan(this.form).then(res => {
-          if (res.code == 200) {
-            this.$message.success('鏂板鎴愬姛')
-            this.draftClear('addVerificationYearPlanDiaForm')
-            this.draftClear('addVerificationYearPlanDiaRows')
-            this.closeDialog()
-            this.$emit('closeDia')
-          }
-          this.submitFormLoading = false
-        }).catch(err => {
-          this.submitFormLoading = false
-        })
-      }
-    },
-    closeDialog() {
-      this.draftStop('addVerificationYearPlanDiaForm')
-      this.draftStop('addVerificationYearPlanDiaRows')
-      this.applicationForm = false
-    },
-    // 鑾峰彇鎵�鏈夎澶�
-    getEquipOptions() {
-      this.equipOptions = []
-      deviceScopeSearch({ status: 0 }).then(res => {
-        if (res.code === 200 && res.data) {
-          this.equipOptions = res.data.map(m => {
-            m.value = m.managementNumber
-            m.label = m.deviceName
-            return m
-          })
-        }
-      }).catch(error => {
-        console.error(error)
-      })
-    },
-    getUserList() {
-      selectUserCondition().then(res => {
-        let data = [];
-        res.data.forEach((a) => {
-          data.push({
-            label: a.name,
-            value: a.id,
-          });
-        });
-        this.userList = data
-      })
-    },
-  },
-}
-</script>
-
-<style scoped></style>
diff --git a/src/views/CNAS/resourceDemand/device/component/addYearPlanDia.vue b/src/views/CNAS/resourceDemand/device/component/addYearPlanDia.vue
index 3269482..09a92ea 100644
--- a/src/views/CNAS/resourceDemand/device/component/addYearPlanDia.vue
+++ b/src/views/CNAS/resourceDemand/device/component/addYearPlanDia.vue
@@ -162,7 +162,13 @@
       this.selectionRows = selection
     },
     changeMachineName() {
-      this.selectionRows.map(val => {
+      const existingIds = new Set(this.calibrationPlanDetailList.map(item => item.deviceId))
+      let skipped = 0
+      this.selectionRows.forEach(val => {
+        if (existingIds.has(val.id)) {
+          skipped++
+          return
+        }
         // 灏� val.nextCalibrationDate 杞崲涓� Date 瀵硅薄骞跺噺鍘� 5 澶�
         let nextCalibrationDate = val.nextCalibrationDate ? new Date(val.nextCalibrationDate) : null;
         if (nextCalibrationDate) {
@@ -177,7 +183,11 @@
           verificationUnit: val.calibrationServices,
           deviceAmount: 1
         })
+        existingIds.add(val.id)
       })
+      if (skipped > 0) {
+        this.$message.warning(`宸茶烦杩� ${skipped} 鍙板凡鍦ㄨ鍒掍腑鐨勮澶嘸)
+      }
       this.addEquipDia = false
       this.rowDrop()
     },
@@ -209,6 +219,18 @@
     },
     // 鎻愪氦鏂板
     submitForm() {
+      if (!this.form.planName) {
+        this.$message.warning('璇疯緭鍏ヨ鍒掑悕绉�')
+        return
+      }
+      if (!this.form.planYear) {
+        this.$message.warning('璇烽�夋嫨骞翠唤')
+        return
+      }
+      if (!this.calibrationPlanDetailList.length) {
+        this.$message.warning('璇锋坊鍔犺澶�')
+        return
+      }
       this.form.calibrationPlanDetailList = this.HaveJson(this.calibrationPlanDetailList)
       this.submitFormLoading = true
       if (this.operationType === 'add') {
@@ -225,7 +247,7 @@
       } else {
         updateDeviceCalibrationPlan(this.form).then(res => {
           if (res.code == 200) {
-            this.$message.success('鏂板鎴愬姛')
+            this.$message.success('淇敼鎴愬姛')
             this.closeDialog()
             this.$emit('closeDia')
           }
diff --git a/src/views/CNAS/resourceDemand/device/component/applicationForm.vue b/src/views/CNAS/resourceDemand/device/component/applicationForm.vue
index 290e701..6adbb02 100644
--- a/src/views/CNAS/resourceDemand/device/component/applicationForm.vue
+++ b/src/views/CNAS/resourceDemand/device/component/applicationForm.vue
@@ -8,7 +8,7 @@
         <el-step title="璁¢噺瀹ゆ剰瑙�" @click="setStep(2)"></el-step>
         <el-step title="鎵瑰噯浜�" @click="setStep(3)"></el-step>
       </el-steps>
-      <el-form ref="modelForm" :model="form" :rules="rules" label-width="160px">
+      <el-form ref="modelForm" :model="form" :rules="rules" label-width="160px" :disabled="!canOperate">
         <el-col v-if="showStep === 0" :span="12">
           <el-form-item label="鍗曚綅鍚嶇О锛�" prop="unitName">
             <el-input v-model="form.unitName" :disabled="currentStep !== 0" clearable size="small"></el-input>
@@ -102,7 +102,7 @@
       </el-form>
       <template #footer><span  class="dialog-footer">
         <el-button @click="resetForm">鍙� 娑�</el-button>
-        <el-button v-if="currentStep !== 4" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
+        <el-button v-if="currentStep !== 4 && canOperate" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
           璁�</el-button>
       </span></template>
     </el-dialog>
@@ -115,6 +115,7 @@
   addDeviceExternalApply,
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
+import { mapGetters } from "@/utils/store-compat";
 export default {
   name: "applicationForm",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -124,6 +125,7 @@
     return {
       dialogVisible: false,
       submitFormLoading: false,
+      canOperate: true,
       form: {
         externalApplyId: '',
         unitName: '',
@@ -161,6 +163,7 @@
     // 鎵撳紑寮规
     openDialog(id) {
       this.dialogVisible = true
+      this.canOperate = true
       this.form.externalApplyId = id
       this.getUserList()
       if (this.form.externalApplyId) {
@@ -189,10 +192,29 @@
             this.currentStep = 4
             this.showStep = 3
           }
+          this.applyPermission()
         }
       }).catch(error => {
         console.error(error)
       })
+    },
+    // 闈炲綋鍓嶇幆鑺傝矗浠讳汉鍙厑璁告煡鐪�
+    applyPermission() {
+      if (this.form.isFinish === 1 || this.currentStep >= 4) {
+        this.canOperate = false
+        return
+      }
+      const responsibleList = [
+        this.form.applicantUser,
+        this.form.departmentHeadUser,
+        this.form.meteringRoomUser,
+        this.form.approverUser,
+      ]
+      const responsible = responsibleList[this.currentStep]
+      this.canOperate = !responsible || responsible === this.nickName
+      if (!this.canOperate) {
+        this.$message.warning('褰撳墠鐜妭璐d换浜轰负锛�' + responsible + '锛屾偍鍙兘鏌ョ湅')
+      }
     },
     setStep(step) {
       this.showStep = step
@@ -202,6 +224,7 @@
       this.form.flowType = this.currentStep
       this.$refs.modelForm.validate((valid) => {
         if (valid) {
+          this.submitFormLoading = true
           addDeviceExternalApply(this.form).then(res => {
             if (res.code == 200) {
               this.$message.success('鏂板鎴愬姛')
@@ -225,6 +248,9 @@
       })
     },
   },
+  computed: {
+    ...mapGetters(["nickName"]),
+  },
 }
 </script>
 
diff --git a/src/views/CNAS/resourceDemand/device/component/borrow.vue b/src/views/CNAS/resourceDemand/device/component/borrow.vue
index 90f69da..326c12e 100644
--- a/src/views/CNAS/resourceDemand/device/component/borrow.vue
+++ b/src/views/CNAS/resourceDemand/device/component/borrow.vue
@@ -26,7 +26,7 @@
         <el-step style="cursor:pointer" v-for="(v, i) in steps" :title="v" :key="i"
           @click="choiceStep(i)"></el-step>
       </el-steps>
-      <el-form ref="form" :model="form" :rules="rules" label-width="130px">
+      <el-form ref="form" :model="form" :rules="rules" label-width="130px" :disabled="!canOperate">
         <div v-show="currentStepClick === 0">
           <el-card style="margin-top: 1em; height: 51vh; overflow-y: scroll;">
             <!-- 鏂板璁惧浜嬭褰曞崱鐗� -->
@@ -57,7 +57,7 @@
               </el-col>
               <el-col :span="12">
                 <el-form-item label="鍊熺敤浜鸿仈绯绘柟寮忥細" prop="borrowerContactInformation" label-width="150px">
-                  <el-input v-model="form.borrowerContactInformation" size="small"></el-input>
+                  <el-input v-model="form.borrowerContactInformation" size="small" :disabled="currentStep > 0"></el-input>
                 </el-form-item>
               </el-col>
               <el-col :span="12">
@@ -81,13 +81,13 @@
                 <el-form-item label="鐩稿叧闄勪欢锛�" prop="fileName">
                   <el-input v-model="form.fileName" disabled size="small"
                     :style="`width: ${currentStep == 0 ? '88%' : '100%'};`">
-                    <template #append><el-button  v-if="currentStep === 0" :icon="$icon('el-icon-delete-solid')"
+                    <template #append><el-button  v-if="currentStep === 0 && canOperate" :icon="$icon('el-icon-delete-solid')"
                       @click="deleteFile"></el-button></template>
                   </el-input>
                   <el-upload ref="upload" style="float: right;" :action="action" :show-file-list="false"
-                    :on-success="onSuccess" :disabled="currentStep !== 0" :headers="uploadHeader">
+                    :on-success="onSuccess" :disabled="currentStep !== 0 || !canOperate" :headers="uploadHeader">
                     <template #trigger><el-button style="position: relative;top: -4px" class="uploadFile"  size="small"
-                      type="primary" v-if="currentStep === 0">闄勪欢涓婁紶</el-button></template>
+                      type="primary" v-if="currentStep === 0 && canOperate">闄勪欢涓婁紶</el-button></template>
                   </el-upload>
                 </el-form-item>
               </el-col>
@@ -170,9 +170,9 @@
         </div>
       </el-form>
       <template #footer><span  class="dialog-footer">
-        <el-button @click="submitForm('3reject')" v-if="currentStep !== 0 && currentStep !== 2">椹冲洖</el-button>
-        <el-button @click="submitForm('2save')" v-if="currentStep === 0">淇濆瓨</el-button>
-        <el-button type="primary" v-if="currentStep !== 2" @click="submitForm('1submit')">{{ currentStep === 0 ? '鎻愪氦' :
+        <el-button :loading="submitLoading" @click="submitForm('3reject')" v-if="currentStep !== 0 && currentStep !== 2 && canOperate">椹冲洖</el-button>
+        <el-button :loading="submitLoading" @click="submitForm('2save')" v-if="currentStep === 0 && canOperate">淇濆瓨</el-button>
+        <el-button :loading="submitLoading" type="primary" v-if="currentStep !== 2 && canOperate" @click="submitForm('1submit')">{{ currentStep === 0 ? '鎻愪氦' :
           '閫氳繃'
           }}</el-button>
       </span></template>
@@ -183,7 +183,7 @@
         </el-table-column>
         <el-table-column prop="operator" label="鎿嶄綔浜�" width="180">
         </el-table-column>
-        <el-table-column prop="operationTime" label="鎿嶄綔鏃ユ湡" width="180">
+        <el-table-column prop="operationTime" label="鎿嶄綔鏃ユ湡" width="180" :formatter="formatDateCell">
         </el-table-column>
         <el-table-column prop="operationType" label="鎻愪氦绫诲瀷">
         </el-table-column>
@@ -207,6 +207,8 @@
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
 import { mapGetters } from "@/utils/store-compat";
+import { formatListDate } from './dateFormat'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   props: {
     clickNodeVal: {
@@ -223,9 +225,10 @@
     return {
       dialogVisible: false,
       dialogVisible0: false,
+      canOperate: true,
       currentStep: 0, // 姝ラ鏉℃樉绀虹鍑犳
       currentStepClick: 0, // 鐐瑰嚮姝ラ鏉″彉鍖�
-      steps: ['鍊熷嚭', '鍊熺敤'],
+      steps: ['鍊熷嚭', '褰掕繕'],
       responsibleOptions: [], // 涓嬬幆鑺傝礋璐d汉list
       form: {
         processNumber: null,
@@ -251,6 +254,7 @@
       },
       deviceLogs: [],
       outLoading: false,
+      submitLoading: false,
       recipientStateList: [{
         value: 0,
         type: 'success',
@@ -279,18 +283,20 @@
         },
         { label: "鍊熺敤浜�", prop: "recipientUser" },
         { label: "鍊熺敤浜鸿仈绯绘柟寮�", prop: "borrowerContactInformation", width: '140px' },
-        { label: "鍊熺敤鏃ユ湡", prop: "recipientTime" },
+        { label: "鍊熺敤鏃ユ湡", prop: "recipientTime", formatData: (params) => formatListDate(params) },
         {
           label: "鍊熺敤鏃剁姸鎬�", prop: "recipientState", dataType: "tag",
           formatData: (params) => {
-            return this.recipientStateList.find((m) => m.value == params).label;
+            const item = this.recipientStateList.find((m) => m.value == params)
+            return item ? item.label : '-'
           },
           formatType: (params) => {
-            return this.recipientStateList.find((m) => m.value == params).type;
+            const item = this.recipientStateList.find((m) => m.value == params)
+            return item ? item.type : 'info'
           },
         },
         { label: "鍊熷嚭浜�", prop: "submitUser" },
-        { label: "鍊熷嚭鏃ユ湡", prop: "createTime" },
+        { label: "鍊熷嚭鏃ユ湡", prop: "createTime", formatData: (params) => formatListDate(params) },
         {
           label: "褰撳墠鐘舵��", prop: "nowState"
         },
@@ -337,7 +343,7 @@
     // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
     clickNodeVal(newVal) {
       if (newVal.value) {
-        thisqueryParams.deviceId = this.clickNodeVal.value
+        this.queryParams.deviceId = this.clickNodeVal.value
         this.refreshTable()
       }
     },
@@ -362,6 +368,9 @@
     this.refreshTable()
   },
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     getList() {
       this.tableLoading = true;
       let param = { ...this.queryParams, ...this.page };
@@ -384,7 +393,7 @@
       this.getList();
     },
     refresh() {
-      this.queryParams = {};
+      this.queryParams = { deviceId: this.clickNodeVal.value };
       this.page.current = 1;
       this.getList();
     },
@@ -445,12 +454,16 @@
           this.form.nowState = currentStepAction === 2 ? '鍏抽棴' : this.steps[currentStepAction]
           this.form.deviceId = this.clickNodeVal.value
           delete this.form.deviceLogs
+          this.submitLoading = true
           saveDeviceBorrow(this.form).then(res => {
             if (res.code == 200) {
               this.$message.success('鎻愪氦鎴愬姛')
               this.dialogVisible = false
               this.refreshTable()
             }
+            this.submitLoading = false
+          }).catch(err => {
+            this.submitLoading = false
           })
         } else {
           let step = this.steps[this.currentStep]
@@ -467,6 +480,8 @@
         deleteCNASFile({ fileName: this.form.fileName }).then(res => {
           if (res.code == 200) {
             this.$message.success('鍒犻櫎鎴愬姛锛�')
+            this.form.fileName = null
+            this.form.url = null
           }
         })
       }).catch(() => {
@@ -510,12 +525,31 @@
             this.currentStepClick = i
           }
           console.log(this.currentStepClick)
+          this.applyPermission()
           this.dialogVisible = true
         }
       })
     },
+    // 闈炲綋鍓嶇幆鑺傝矗浠讳汉鍙厑璁告煡鐪�
+    applyPermission() {
+      if (this.form.nowState === '鍏抽棴') {
+        this.canOperate = false
+        return
+      }
+      let responsible = null
+      if (this.form.nowState === '褰掕繕') {
+        responsible = this.form.nowUser
+      } else if (this.form.nowState === '鍊熷嚭') {
+        responsible = this.form.submitOperationUser
+      }
+      this.canOperate = !responsible || responsible === this.nickName
+      if (!this.canOperate) {
+        this.$message.warning('褰撳墠鐜妭璐d换浜轰负锛�' + responsible + '锛屾偍鍙兘鏌ョ湅')
+      }
+    },
     // 鏂板
     add() {
+      this.canOperate = true
       this.dialogVisible = true
       this.form = {
         processNumber: null,
@@ -523,10 +557,11 @@
         unifyNumber: null,
         recipientUser: null,
         recipientTime: null,
+        recipientState: 0,
         nextUser: null,
         rebackUser: null,
         rebackTime: null,
-        receiveState: null,
+        receiveState: 0,
         deviceUser: null,
         fileName: null,
       }
@@ -538,11 +573,10 @@
       this.outLoading = true
       deviceBorrowExport({ deviceId: this.clickNodeVal.value }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], {
-          type: 'application/force-download'
-        })
         const filename = decodeURI(this.clickNodeVal.label + '璁惧鍊熷嚭缁熻' + '.xlsx')
-        this.$download.saveAs(blob, filename)
+        saveBlobOrShowError(res, filename, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     handleLookList(row) {
diff --git a/src/views/CNAS/resourceDemand/device/component/calibration.vue b/src/views/CNAS/resourceDemand/device/component/calibration.vue
index 6613757..36a3061 100644
--- a/src/views/CNAS/resourceDemand/device/component/calibration.vue
+++ b/src/views/CNAS/resourceDemand/device/component/calibration.vue
@@ -3,7 +3,7 @@
   <div>
     <div class="btnS">
       <el-button size="small" type="primary" @click="calibrationMaintenance()">鏍″噯椤圭洰缁存姢</el-button>
-      <el-button size="small" type="primary" @click="add('add')">娣诲姞鏍″噯璁板綍</el-button>
+      <el-button size="small" type="primary" @click="add()">娣诲姞鏍″噯璁板綍</el-button>
     </div>
     <div class="tables" style="margin-top: 10px;">
       <el-table :data="tableData" height="calc(100vh - 20em)" border>
@@ -21,11 +21,15 @@
         </el-table-column>
         <el-table-column label="鏍″噯璇佷功缂栧彿" min-width="150" prop="certificateSerialNumber"></el-table-column>
         <el-table-column label="璇存槑" min-width="150" prop="remark" show-overflow-tooltip></el-table-column>
-        <el-table-column label="鏍″噯鏃ユ湡" min-width="150" prop="calibrationDate"></el-table-column>
-        <el-table-column label="涓嬫鏍″噯鏃ユ湡" min-width="150" prop="nextCalibrationDate"></el-table-column>
-        <el-table-column label="纭鏃ユ湡" min-width="150" prop="confirmDate"></el-table-column>
+        <el-table-column label="鏍″噯鏃ユ湡" min-width="150" prop="calibrationDate"
+          :formatter="formatDateCell"></el-table-column>
+        <el-table-column label="涓嬫鏍″噯鏃ユ湡" min-width="150" prop="nextCalibrationDate"
+          :formatter="formatDateCell"></el-table-column>
+        <el-table-column label="纭鏃ユ湡" min-width="150" prop="confirmDate"
+          :formatter="formatDateCell"></el-table-column>
         <el-table-column label="鐧昏浜�" min-width="150" prop="createUser"></el-table-column>
-        <el-table-column label="鐧昏鏃ユ湡" min-width="150" prop="createTime"></el-table-column>
+        <el-table-column label="鐧昏鏃ユ湡" min-width="150" prop="createTime"
+          :formatter="formatDateCell"></el-table-column>
         <el-table-column fixed="right" label="鎿嶄綔" min-width="180" align="center">
           <template #default="{ row }">
             <el-button size="small" link type="primary" @click="handleAttachmentClick(row)">涓嬭浇闄勪欢</el-button>
@@ -34,7 +38,7 @@
           </template>
         </el-table-column>
       </el-table>
-      <el-pagination :current-page="1" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
+      <el-pagination :current-page="search.current" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
         :total="search.total" layout="->,total, sizes, prev, pager, next, jumper"
         @size-change="handleSizeChange" @current-change="handleCurrentChange" background>
       </el-pagination>
@@ -85,7 +89,7 @@
         <el-table-column label="鏈�澶у厑璁歌宸�" prop="maxPermissibleError"></el-table-column>
         <el-table-column label="鍒ゅ畾鏍囧噯" prop="judgmentCriteria"></el-table-column>
         <el-table-column label="鍒涘缓浜�" prop="createdBy"></el-table-column>
-        <el-table-column label="鍒涘缓鏃堕棿" prop="creationTime"></el-table-column>
+        <el-table-column label="鍒涘缓鏃堕棿" prop="creationTime" :formatter="formatDateCell"></el-table-column>
         <el-table-column fixed="right" label="鎿嶄綔">
           <template #default="scope">
             <el-button size="small" link type="primary" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
@@ -94,178 +98,25 @@
       </el-table>
     </el-dialog>
 
-    <!-- 娣诲姞鏍″噯璁板綍 -->
-    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible1"
-      title="娣诲姞鏍″噯璁板綍" top="5vh" width="80%" @close="resetCalibrationRecord">
-      <div style="height: 70vh;overflow-y: auto;overflow-x: hidden;">
-        <h4>
-          <div style="display: flex;align-items: center;">
-            <span class="line"></span>
-            <span>娣诲姞璁惧鏍″噯璁板綍</span>
-          </div>
-        </h4>
-        <el-form ref="calibrationRecord" :model="calibrationRecord" :rules="formRules" label-position="right"
-          label-width="120px">
-          <el-row>
-            <el-col :span="6">
-              <el-form-item label="鏍″噯鏈嶅姟鏈烘瀯:" prop="unitOfMeasure">
-                <el-select v-model="calibrationRecord.unitOfMeasure" :disabled="operationType === 'view'" 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>
-            </el-col>
-            <el-col :span="8">
-              <el-form-item label="鏍″噯鏃ユ湡:" prop="calibrationDate">
-                <el-date-picker v-model="calibrationRecord.calibrationDate" :disabled="operationType === 'view'"
-                  format="YYYY-MM-DD" placeholder="閫夋嫨鏃ユ湡" size="small" style="width: 90%" type="date"
-                  value-format="YYYY-MM-DD" @change="getNextCalibrationDate">
-                </el-date-picker>
-              </el-form-item>
-            </el-col>
-            <el-col :span="10">
-              <el-form-item label="涓嬫鏍″噯鏃ユ湡:" label-width="140px">
-                <el-date-picker v-model="calibrationRecord.nextCalibrationDate" disabled format="YYYY-MM-DD"
-                  placeholder="閫夋嫨鏃ユ湡" size="small" style="width: 90%" type="date" value-format="YYYY-MM-DD">
-                </el-date-picker>
-              </el-form-item>
-            </el-col>
-            <el-col :span="6">
-              <el-form-item label="璁$畻鍣ㄥ叿:" prop="calculatingApparatus">
-                <el-input v-model="calibrationRecord.calculatingApparatus" :disabled="operationType === 'view'"
-                  size="small"></el-input>
-              </el-form-item>
-            </el-col>
-            <el-col :span="8">
-              <el-form-item label="璁$畻鏍囧噯閲忕▼:" prop="standardRange">
-                <el-input v-model="calibrationRecord.standardRange" :disabled="operationType === 'view'" size="small"
-                  style="width: 90%"></el-input>
-              </el-form-item>
-            </el-col>
-            <el-col :span="10">
-              <el-form-item label="璁¢噺鏍囧噯涓嶇‘瀹氬害:" label-width="140px" prop="calibrationStandardUncertainty">
-                <el-input v-model="calibrationRecord.calibrationStandardUncertainty"
-                  :disabled="operationType === 'view'" size="small" style="width: 90%"></el-input>
-              </el-form-item>
-            </el-col>
-            <el-col :span="6">
-              <el-form-item label="鎵�渚濇嵁鏂囦欢:" prop="byDocument">
-                <el-input v-model="calibrationRecord.byDocument" :disabled="operationType === 'view'"
-                  size="small"></el-input>
-              </el-form-item>
-            </el-col>
-            <el-col :span="8">
-              <el-form-item label="璇佷功缂栧彿:" prop="certificateSerialNumber">
-                <el-input v-model="calibrationRecord.certificateSerialNumber" :disabled="operationType === 'view'"
-                  size="small" style="width: 90%"></el-input>
-              </el-form-item>
-            </el-col>
-            <el-col :span="10">
-              <el-form-item label="鐘舵��:" label-width="140px" prop="status" required>
-                <el-radio-group v-model="calibrationRecord.status" :disabled="operationType === 'view'">
-                  <el-radio value="0yes">鍚堟牸</el-radio>
-                  <el-radio value="1no">涓嶅悎鏍�</el-radio>
-                  <el-radio value="2other">鍏朵粬</el-radio>
-                </el-radio-group>
-              </el-form-item>
-            </el-col>
-            <el-col :span="6">
-              <el-form-item label="纭鏃ユ湡:">
-                <el-date-picker v-model="calibrationRecord.confirmDate" :disabled="operationType === 'view'"
-                  format="YYYY-MM-DD HH:mm:ss" placeholder="閫夋嫨鏃ユ湡" size="small" style="width: 100%" type="datetime"
-                  value-format="YYYY-MM-DD HH:mm:ss">
-                </el-date-picker>
-              </el-form-item>
-            </el-col>
-            <el-col :span="17">
-              <el-form-item label="闄勪欢锛�" prop="fileName">
-                <el-input v-model="calibrationRecord.fileName"
-                  :style="`width: ${operationType === 'add' ? '85%' : '100%'};}`" disabled size="small">
-                  <template #append><el-button v-if="operationType === 'add'"  :icon="$icon('el-icon-delete-solid')"
-                    @click="deleteFile"></el-button></template>
-                </el-input>
-                <el-upload v-if="operationType === 'add'" ref="upload" :action="action" :before-upload="beforeUpload"
-                  :headers="uploadHeader" :limit="1" :on-error="onError" :on-success="handleSuccessUp"
-                  :show-file-list="false" style="float: right;">
-                  <el-button :loading="upLoading" size="small" style="position: relative; top: -4px;"
-                    type="primary">闄勪欢涓婁紶
-                  </el-button>
-                </el-upload>
-              </el-form-item>
-            </el-col>
-            <el-col :span="24">
-              <el-form-item label="澶囨敞:">
-                <el-input v-model="calibrationRecord.remark" :disabled="operationType === 'view'" :rows="3" size="small"
-                  style="width: 96%" type="textarea"></el-input>
-              </el-form-item>
-            </el-col>
-          </el-row>
-        </el-form>
-        <h4>
-          <span style="display: flex;align-items: center;">
-            <span class="line"></span><span>鏍″噯鏉$洰纭缁撴灉</span>
-          </span>
-        </h4>
-        <el-table ref="calibrateTable" :data="calibrateParams" border>
-          <el-table-column label="缂栧彿" type="index" width="60"></el-table-column>
-          <el-table-column label="璁¢噺鍙傛暟" prop="measurementParameter"></el-table-column>
-          <el-table-column label="閲忕▼鑼冨洿" prop="rangeOfMeasurement"></el-table-column>
-          <el-table-column label="鏈�澶у厑璁歌宸�" prop="maxPermissibleError"></el-table-column>
-          <el-table-column label="鍒ゅ畾鏍囧噯" prop="judgmentCriteria"></el-table-column>
-          <el-table-column label="鏄惁鏍″噯" prop="isCalibration">
-            <template #header="scope">
-              <span class="required-span">* </span>鏄惁鏍″噯
-            </template>
-            <template #default="scope">
-              <el-radio-group v-model="scope.row.isCalibration" :disabled="operationType === 'view'">
-                <el-radio value="0yes">鏄�</el-radio>
-                <el-radio value="1no">鍚�</el-radio>
-              </el-radio-group>
-            </template>
-          </el-table-column>
-          <el-table-column label="鍒ゅ畾缁撴灉" min-width="140" prop="result">
-            <template #header="scope">
-              <span class="required-span">* </span>鍒ゅ畾缁撴灉
-            </template>
-            <template #default="scope">
-              <el-radio-group v-model="scope.row.result" :disabled="operationType === 'view'" @change="checkRadio()">
-                <el-radio value="0yes">鍚堟牸</el-radio>
-                <el-radio value="1no">涓嶅悎鏍�</el-radio>
-                <el-radio value="2other">鍏朵粬</el-radio>
-              </el-radio-group>
-            </template>
-          </el-table-column>
-          <el-table-column label="鍗曢」缁撴灉璇存槑" prop="singleResultStatement">
-            <template #default="scope">
-              <el-input v-model="scope.row.singleResultStatement" :disabled="operationType === 'view'"
-                size="small"></el-input>
-            </template>
-          </el-table-column>
-        </el-table>
-      </div>
-      <template #footer><span  class="dialog-footer">
-        <el-button v-if="operationType === 'add'" @click="dialogVisible1 = false">鍙� 娑�</el-button>
-        <el-button v-if="operationType === 'add'" :loading="addRecordLoading" type="primary" @click="addRecord">纭�
-          瀹�</el-button>
-      </span></template>
-    </el-dialog>
+    <!-- 娣诲姞/鏌ョ湅鏍″噯璁板綍寮圭獥 -->
+    <calibration-record-dia ref="calibrationRecordDia"
+      @success="getTableList(clickNodeVal.value)"></calibration-record-dia>
   </div>
 </template>
 
 <script>
 import {
   deviceMetricRecordPage,
-  showDeviceMetricsCopy,
   deleteDeviceMetricRecord,
-  deleteCNASFile,
   selectDeviceMetric,
   deleteDeviceMetrics,
-  addOrUpdateDeviceMetricRecord,
   saveOrUpdateDeviceMetric
 } from '@/api/cnas/resourceDemand/device.js'
-import { selectQualifiedSupplierManagementPage } from '@/api/cnas/externalService/supplierManage/supplierManage'
+import CalibrationRecordDia from './calibrationRecordDia.vue'
+import { formatListDate } from './dateFormat'
 import { mapGetters } from "@/utils/store-compat";
 export default {
+  components: { CalibrationRecordDia },
   props: {
     clickNodeVal: {
       type: Object,
@@ -280,33 +131,8 @@
       calibrateParams: [],
       calibrateParamsLoading: false,
       addCalibrateLoading: false,
-      calibrationRecord: {
-        unitOfMeasure: '', // 璁¢噺鍗曚綅
-        calibrationDate: null, // 鏍″噯鏃ユ湡
-        nextCalibrationDate: null, // 涓嬫鏍″噯鏃ユ湡
-        calculatingApparatus: '', // 璁$畻鍣ㄥ叿
-        confirmDate: null, // 纭鏃ユ湡
-        standardRange: '', // 璁$畻鏍囧噯閲忕▼
-        calibrationStandardUncertainty: '', // 璁¢噺鏍囧噯涓嶇‘瀹氬害
-        byDocument: '', // 渚濇嵁鏂囦欢
-        certificateSerialNumber: '', // 璇佷功缂栧彿
-        status: '', // 鐘舵��
-        remark: '', // 澶囨敞
-        systemFileName: '', //
-        fileName: '', //
-      },
-      formRules: {
-        unitOfMeasure: [{ required: true, message: '璇烽�夋嫨鏍″噯鏈嶅姟鏈烘瀯', trigger: 'change' }],
-        calibrationDate: [{ required: true, message: '璇烽�夋嫨鏍″噯鏃ユ湡', trigger: 'change' }],
-        calculatingApparatus: [{ required: true, message: '璇疯緭鍏ヨ绠楀櫒鍏�', trigger: 'blur' }],
-        standardRange: [{ required: true, message: '璇疯緭鍏ヨ绠楁爣鍑嗛噺绋�', trigger: 'blur' }],
-        calibrationStandardUncertainty: [{ required: true, message: '璇疯緭鍏ヨ閲忔爣鍑嗕笉纭畾搴�', trigger: 'blur' }],
-        byDocument: [{ required: true, message: '璇疯緭鍏ユ墍渚濇嵁鏂囦欢', trigger: 'blur' }],
-        status: [{ required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }],
-      },
       tableData: [],
       dialogVisible0: false,
-      dialogVisible1: false,
       form0: {
         measurementParameter: '', // 璁¢噺鍙傛暟
         rangeOfMeasurement: '',
@@ -330,10 +156,6 @@
           { required: true, message: '璇疯緭鍏ュ垽瀹氭爣鍑�', trigger: 'blur' }
         ],
       },
-      addRecordLoading: false,
-      upLoading: false,
-      operationType: '',
-      qualifiedSupplierNames: [],
       search: {
         size: 20,
         current: 1,
@@ -343,50 +165,15 @@
   },
   // 鐢ㄤ簬涓婁紶鏂囦欢鐨勪俊鎭�
   computed: {
-    // 鏍″噯鏈嶅姟鏈烘瀯涓嬫媺閫夐」锛堝悎鏍间緵搴斿晢 + 褰撳墠鍊煎厹搴曪級
-    calibrationServiceOptions() {
-      const list = this.qualifiedSupplierNames.slice();
-      const value = this.calibrationRecord.unitOfMeasure;
-      if (value && list.indexOf(value) === -1) list.push(value);
-      return list;
-    },
     ...mapGetters(["nickName"]),
-    action() {
-      return this.javaApi + '/personBasicInfo/saveCNASFile'
-    }
   },
   mounted() {
-    this.obtainQualifiedSupplierList()
     //鑾峰彇鎿嶄綔璁板綍淇℃伅
     this.getTableList(this.clickNodeVal.value) // 鑾峰彇璁惧鏍″噯鍒楄〃鏁版嵁
   },
   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))];
-        }
-      });
-    },
-    //鐘舵�佸垽瀹�
-    checkRadio() {
-      let resultList = this.calibrateParams.map(ele => ele.result)
-      if (resultList && resultList.filter(ele => ele == '1no').length > 0) {
-        this.calibrationRecord.status = '1no'
-      } else if (resultList && resultList.filter(ele => ele == '2other').length == resultList.length) {
-        this.calibrationRecord.status = '2other'
-      } else if (resultList && resultList.filter(ele => ele == '0yes').length == resultList.length) {
-        this.calibrationRecord.status = '0yes'
-      }
-    },
-    getNextCalibrationDate(val) {
-      let oneYearLaterDate = new Date(val)
-      oneYearLaterDate.setFullYear(oneYearLaterDate.getFullYear() + 1);
-      oneYearLaterDate.setDate(oneYearLaterDate.getDate() - 1);
-      // let obj = oneYearLaterDate.toISOString().split('T')[0];
-      this.calibrationRecord.nextCalibrationDate = oneYearLaterDate
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
     },
     handleSizeChange(val) {
       this.search.size = val
@@ -402,20 +189,13 @@
         this.search.total = res.data.total
       })
     },
-    // 娣诲姞鏍告煡璁板綍
-    add(type) {
-      this.operationType = type
-      this.dialogVisible1 = true
-      this.getXmsg()
+    // 娣诲姞鏍″噯璁板綍
+    add() {
+      this.$refs.calibrationRecordDia.open(this.clickNodeVal.value, 'add')
     },
     // 鏌ョ湅璇︽儏
     handleViewClick(type, row) {
-      showDeviceMetricsCopy({ id: row.id, type: 'calibrate' }).then(res => {
-        this.calibrateParams = res.data
-      })
-      this.calibrationRecord = { ...row }
-      this.operationType = type
-      this.dialogVisible1 = true
+      this.$refs.calibrationRecordDia.open(this.clickNodeVal.value, type, row)
     },
     // 琛ㄦ牸鍒犻櫎鎿嶄綔
     handleDeleteClick(row) {
@@ -436,28 +216,14 @@
       })
     },
     handleAttachmentClick(row) {
-      this.$download.saveAs(row.systemFileName, row.systemFileName)
-    },
-    deleteFile() {
-      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎鏂囦欢, 鏄惁缁х画?', '鎻愮ず', {
-        confirmButtonText: '纭畾',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning'
-      }).then(() => {
-        deleteCNASFile({ fileName: this.calibrationRecord.systemFileName }).then(res => {
-          this.calibrationRecord.fileName = ''
-          this.$refs.upload.clearFiles()
-          if (res.code == 200) {
-            this.$message.success('鍒犻櫎鎴愬姛锛�')
-          }
-        })
-      }).catch((err) => {
-        console.log('err----', err)
-        this.$message({
-          type: 'info',
-          message: '宸插彇娑堝垹闄�'
-        });
-      });
+      if (!row.systemFileName) {
+        this.$message.warning('鏈笂浼犳枃浠讹紒')
+        return
+      }
+      // 鍥剧墖瀛� /img/锛屽叾浠栨枃妗e瓨 /word/
+      const isImage = /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(row.systemFileName)
+      const url = this.javaApi + (isImage ? '/img/' : '/word/') + row.systemFileName
+      this.$download.saveAs(url, row.fileName || row.systemFileName)
     },
     // 鏍″噯椤圭洰缁存姢
     calibrationMaintenance() {
@@ -520,69 +286,6 @@
         }
       })
     },
-    addRecord() {
-      this.$refs['calibrationRecord'].validate((valid) => {
-        if (valid) {
-          try {
-            if (this.calibrateParams.some(m => m.isCalibration === undefined)) {
-              this.$message.error('璇烽�夋嫨鏄惁鏍″噯')
-              return
-            }
-            if (!this.calibrateParams.every(m => m.result !== undefined)) {
-              this.$message.error('璇烽�夋嫨鍒ゅ畾缁撴灉')
-              return
-            }
-            this.addRecordLoading = true
-            this.calibrationRecord.deviceId = this.clickNodeVal.value;
-            this.calibrationRecord.createUser = this.nickName
-            this.calibrationRecord.type = 'calibrate'
-            this.calibrationRecord.deviceMetricsCopyList = this.calibrateParams
-            addOrUpdateDeviceMetricRecord(this.calibrationRecord).then(res => {
-              if (res.code == 200) {
-                this.$message.success('娣诲姞鎴愬姛')
-                this.dialogVisible1 = false
-                this.getTableList(this.clickNodeVal.value)
-              }
-              this.addRecordLoading = false
-            })
-          } catch (e) {
-            console.log('addRecord---', e)
-            this.addRecordLoading = false
-          }
-        } else {
-          this.$message.warning('鏈夊繀濉」鏈~');
-        }
-      })
-    },
-    resetCalibrationRecord() {
-      this.$refs.calibrationRecord.resetFields()
-    },
-    // 涓婁紶闄勪欢
-    handleSuccessUp(response, file) {
-      if (response.code == 200) {
-        // 鍦ㄤ繚瀛樿祴鍊兼柊鏂囦欢
-        this.calibrationRecord.fileName = file.name
-        this.calibrationRecord.systemFileName = response.data
-        this.upLoading = false;
-      } else {
-        this.upLoading = false;
-        this.$message.error(response.message)
-      }
-    },
-    beforeUpload(file) {
-      if (file.size > 1024 * 1024 * 10) {
-        this.$message.error('涓婁紶鏂囦欢涓嶈秴杩�10M');
-        this.$refs.upload.clearFiles()
-        return false;
-      } else {
-        this.upLoading = true;
-        return true;
-      }
-    },
-    onError(err, file, fileList) {
-      this.$message.error('涓婁紶澶辫触')
-      this.$refs.upload.clearFiles()
-    },
     // end
   },
   watch: {
@@ -590,23 +293,6 @@
     clickNodeVal(newVal) {
       if (newVal.value) {
         this.getTableList(newVal.value);
-      }
-    },
-    dialogVisible1(newVal) {
-      if (newVal === false) {
-        this.calibrateParams = []
-        this.calibrationRecord = {
-          unitOfMeasure: '', // 璁¢噺鍗曚綅
-          calibrationDate: null, // 鏍″噯鏃ユ湡
-          nextCalibrationDate: null, // 涓嬫鏍″噯鏃ユ湡
-          calculatingApparatus: '', // 璁$畻鍣ㄥ叿
-          standardRange: '', // 璁$畻鏍囧噯閲忕▼
-          calibrationStandardUncertainty: '', // 璁¢噺鏍囧噯涓嶇‘瀹氬害
-          byDocument: '', // 渚濇嵁鏂囦欢
-          certificateSerialNumber: '', // 璇佷功缂栧彿
-          status: '', // 鐘舵��
-          remark: '', // 澶囨敞
-        }
       }
     }
   }
diff --git a/src/views/CNAS/resourceDemand/device/component/calibrationRecordDia.vue b/src/views/CNAS/resourceDemand/device/component/calibrationRecordDia.vue
new file mode 100644
index 0000000..c3507dd
--- /dev/null
+++ b/src/views/CNAS/resourceDemand/device/component/calibrationRecordDia.vue
@@ -0,0 +1,448 @@
+<!-- 璁惧鏍″噯璁板綍寮圭獥锛堟坊鍔�/鏌ョ湅锛夛紝璁惧鏍″噯椤典笌璁惧鏍″噯璁″垝椤靛叡鐢� -->
+<template>
+  <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="visible" title="娣诲姞鏍″噯璁板綍" top="5vh"
+    width="80%" @close="resetCalibrationRecord">
+    <div style="height: 70vh;overflow-y: auto;overflow-x: hidden;">
+      <h4>
+        <div style="display: flex;align-items: center;">
+          <span class="line"></span>
+          <span>娣诲姞璁惧鏍″噯璁板綍</span>
+        </div>
+      </h4>
+      <el-form ref="calibrationRecord" :model="calibrationRecord" :rules="formRules" label-position="right"
+        label-width="120px">
+        <el-row>
+          <el-col :span="6">
+            <el-form-item label="鏍″噯鏈嶅姟鏈烘瀯:" prop="unitOfMeasure">
+              <el-select v-model="calibrationRecord.unitOfMeasure" :disabled="operationType === 'view'" 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>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="鏍″噯鏃ユ湡:" prop="calibrationDate">
+              <el-date-picker v-model="calibrationRecord.calibrationDate" :disabled="operationType === 'view'"
+                format="YYYY-MM-DD" placeholder="閫夋嫨鏃ユ湡" size="small" style="width: 90%" type="date"
+                value-format="YYYY-MM-DD" @change="getNextCalibrationDate">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="10">
+            <el-form-item label="涓嬫鏍″噯鏃ユ湡:" label-width="140px">
+              <el-date-picker v-model="calibrationRecord.nextCalibrationDate" disabled format="YYYY-MM-DD"
+                placeholder="閫夋嫨鏃ユ湡" size="small" style="width: 90%" type="date" value-format="YYYY-MM-DD">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="璁¢噺鍣ㄥ叿:" prop="calculatingApparatus">
+              <el-input v-model="calibrationRecord.calculatingApparatus" :disabled="operationType === 'view'"
+                size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="璁¢噺鏍囧噯閲忕▼:" prop="standardRange">
+              <el-input v-model="calibrationRecord.standardRange" :disabled="operationType === 'view'" size="small"
+                style="width: 90%"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="10">
+            <el-form-item label="璁¢噺鏍囧噯涓嶇‘瀹氬害:" label-width="140px" prop="calibrationStandardUncertainty">
+              <el-input v-model="calibrationRecord.calibrationStandardUncertainty"
+                :disabled="operationType === 'view'" size="small" style="width: 90%"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="鎵�渚濇嵁鏂囦欢:" prop="byDocument">
+              <el-input v-model="calibrationRecord.byDocument" :disabled="operationType === 'view'"
+                size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="璇佷功缂栧彿:" prop="certificateSerialNumber">
+              <el-input v-model="calibrationRecord.certificateSerialNumber" :disabled="operationType === 'view'"
+                size="small" style="width: 90%"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="10">
+            <el-form-item label="鐘舵��:" label-width="140px" prop="status" required>
+              <el-radio-group v-model="calibrationRecord.status" :disabled="operationType === 'view'">
+                <el-radio value="0yes">鍚堟牸</el-radio>
+                <el-radio value="1no">涓嶅悎鏍�</el-radio>
+                <el-radio value="2other">鍏朵粬</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="纭鏃ユ湡:">
+              <el-date-picker v-model="calibrationRecord.confirmDate" :disabled="operationType === 'view'"
+                format="YYYY-MM-DD HH:mm:ss" placeholder="閫夋嫨鏃ユ湡" size="small" style="width: 100%" type="datetime"
+                value-format="YYYY-MM-DD HH:mm:ss">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="17">
+            <el-form-item label="闄勪欢锛�" prop="fileName">
+              <el-input v-model="calibrationRecord.fileName"
+                :style="`width: ${operationType === 'add' ? '85%' : '100%'}`" disabled size="small">
+                <template #append><el-button v-if="operationType === 'add'" :icon="$icon('el-icon-delete-solid')"
+                  @click="deleteFile"></el-button></template>
+              </el-input>
+              <el-upload v-if="operationType === 'add'" ref="upload" :action="action" :before-upload="beforeUpload"
+                :headers="uploadHeader" :limit="1" :on-error="onError" :on-success="handleSuccessUp"
+                :show-file-list="false" style="float: right;">
+                <el-button :loading="upLoading" size="small" style="position: relative; top: -4px;"
+                  type="primary">闄勪欢涓婁紶
+                </el-button>
+              </el-upload>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="澶囨敞:">
+              <el-input v-model="calibrationRecord.remark" :disabled="operationType === 'view'" :rows="3" size="small"
+                style="width: 96%" type="textarea"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <h4>
+        <span style="display: flex;align-items: center;">
+          <span class="line"></span><span>鏍″噯鏉$洰纭缁撴灉</span>
+        </span>
+      </h4>
+      <el-table ref="calibrateTable" :data="calibrateParams" border>
+        <el-table-column label="缂栧彿" type="index" width="60"></el-table-column>
+        <el-table-column label="璁¢噺鍙傛暟" prop="measurementParameter"></el-table-column>
+        <el-table-column label="閲忕▼鑼冨洿" prop="rangeOfMeasurement"></el-table-column>
+        <el-table-column label="鏈�澶у厑璁歌宸�" prop="maxPermissibleError"></el-table-column>
+        <el-table-column label="鍒ゅ畾鏍囧噯" prop="judgmentCriteria"></el-table-column>
+        <el-table-column label="鏄惁鏍″噯" prop="isCalibration">
+          <template #header="scope">
+            <span class="required-span">* </span>鏄惁鏍″噯
+          </template>
+          <template #default="scope">
+            <el-radio-group v-model="scope.row.isCalibration" :disabled="operationType === 'view'">
+              <el-radio value="0yes">鏄�</el-radio>
+              <el-radio value="1no">鍚�</el-radio>
+            </el-radio-group>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍒ゅ畾缁撴灉" min-width="140" prop="result">
+          <template #header="scope">
+            <span class="required-span">* </span>鍒ゅ畾缁撴灉
+          </template>
+          <template #default="scope">
+            <el-radio-group v-model="scope.row.result" :disabled="operationType === 'view'" @change="checkRadio()">
+              <el-radio value="0yes">鍚堟牸</el-radio>
+              <el-radio value="1no">涓嶅悎鏍�</el-radio>
+              <el-radio value="2other">鍏朵粬</el-radio>
+            </el-radio-group>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍗曢」缁撴灉璇存槑" prop="singleResultStatement">
+          <template #default="scope">
+            <el-input v-model="scope.row.singleResultStatement" :disabled="operationType === 'view'"
+              size="small"></el-input>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <template #footer><span class="dialog-footer">
+        <el-button v-if="operationType === 'add'" @click="visible = false">鍙� 娑�</el-button>
+        <el-button v-if="operationType === 'view'" @click="visible = false">鍏� 闂�</el-button>
+        <el-button v-if="operationType === 'add'" :loading="addRecordLoading" type="primary" @click="addRecord">纭�
+          瀹�</el-button>
+      </span></template>
+  </el-dialog>
+</template>
+
+<script>
+import {
+  showDeviceMetricsCopy,
+  deleteCNASFile,
+  selectDeviceMetric,
+  addOrUpdateDeviceMetricRecord,
+  getDeviceById
+} from '@/api/cnas/resourceDemand/device.js'
+import dayjs from 'dayjs'
+import { selectQualifiedSupplierManagementPage } from '@/api/cnas/externalService/supplierManage/supplierManage'
+import { mapGetters } from "@/utils/store-compat";
+export default {
+  name: "calibration-record-dia",
+  data() {
+    return {
+      visible: false,
+      deviceId: null,
+      operationType: '',
+      calibrationCycle: 12,
+      calibrateParams: [],
+      calibrateParamsLoading: false,
+      addRecordLoading: false,
+      upLoading: false,
+      qualifiedSupplierNames: [],
+      calibrationRecord: {
+        unitOfMeasure: '', // 璁¢噺鍗曚綅
+        calibrationDate: null, // 鏍″噯鏃ユ湡
+        nextCalibrationDate: null, // 涓嬫鏍″噯鏃ユ湡
+        calculatingApparatus: '', // 璁¢噺鍣ㄥ叿
+        confirmDate: null, // 纭鏃ユ湡
+        standardRange: '', // 璁¢噺鏍囧噯閲忕▼
+        calibrationStandardUncertainty: '', // 璁¢噺鏍囧噯涓嶇‘瀹氬害
+        byDocument: '', // 渚濇嵁鏂囦欢
+        certificateSerialNumber: '', // 璇佷功缂栧彿
+        status: '', // 鐘舵��
+        remark: '', // 澶囨敞
+        systemFileName: '', //
+        fileName: '', //
+      },
+      formRules: {
+        unitOfMeasure: [{ required: true, message: '璇烽�夋嫨鏍″噯鏈嶅姟鏈烘瀯', trigger: 'change' }],
+        calibrationDate: [{ required: true, message: '璇烽�夋嫨鏍″噯鏃ユ湡', trigger: 'change' }],
+        calculatingApparatus: [{ required: true, message: '璇疯緭鍏ヨ閲忓櫒鍏�', trigger: 'blur' }],
+        standardRange: [{ required: true, message: '璇疯緭鍏ヨ閲忔爣鍑嗛噺绋�', trigger: 'blur' }],
+        calibrationStandardUncertainty: [{ required: true, message: '璇疯緭鍏ヨ閲忔爣鍑嗕笉纭畾搴�', trigger: 'blur' }],
+        byDocument: [{ required: true, message: '璇疯緭鍏ユ墍渚濇嵁鏂囦欢', trigger: 'blur' }],
+        status: [{ required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }],
+      },
+    }
+  },
+  computed: {
+    // 鏍″噯鏈嶅姟鏈烘瀯涓嬫媺閫夐」锛堝悎鏍间緵搴斿晢 + 褰撳墠鍊煎厹搴曪級
+    calibrationServiceOptions() {
+      const list = this.qualifiedSupplierNames.slice();
+      const value = this.calibrationRecord.unitOfMeasure;
+      if (value && list.indexOf(value) === -1) list.push(value);
+      return list;
+    },
+    ...mapGetters(["nickName"]),
+    action() {
+      return this.javaApi + '/personBasicInfo/saveCNASFile'
+    }
+  },
+  mounted() {
+    this.obtainQualifiedSupplierList()
+  },
+  methods: {
+    // 鎵撳紑寮圭獥锛歞eviceId 璁惧id锛泃ype add鏂板/view鏌ョ湅锛況ow 鏌ョ湅鏃剁殑璁板綍琛�
+    open(deviceId, type, row) {
+      this.deviceId = deviceId
+      this.operationType = type
+      if (type === 'view' && row) {
+        showDeviceMetricsCopy({ id: row.id, type: 'calibrate' }).then(res => {
+          this.calibrateParams = res.data
+        })
+        this.calibrationRecord = { ...row }
+      } else {
+        this.getDeviceCycle()
+        this.getXmsg()
+      }
+      this.visible = true
+    },
+    // 鎷夊彇鍚堟牸渚涘簲鍟嗗垪琛紙鏍″噯鏈嶅姟鏈烘瀯涓嬫媺閫夐」锛�
+    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))];
+        }
+      });
+    },
+    //鐘舵�佸垽瀹�
+    checkRadio() {
+      let resultList = this.calibrateParams.map(ele => ele.result)
+      if (resultList && resultList.filter(ele => ele == '1no').length > 0) {
+        this.calibrationRecord.status = '1no'
+      } else if (resultList && resultList.filter(ele => ele == '2other').length == resultList.length) {
+        this.calibrationRecord.status = '2other'
+      } else if (resultList && resultList.filter(ele => ele == '0yes').length == resultList.length) {
+        this.calibrationRecord.status = '0yes'
+      }
+    },
+    // 鏌ヨ璁惧鏍″噯鍛ㄦ湡锛堟湀锛夛紝涓庡悗绔粴鍔ㄨ澶囨。妗堟棩鏈熺殑瑙勫垯淇濇寔涓�鑷�
+    getDeviceCycle() {
+      if (!this.deviceId) {
+        return
+      }
+      getDeviceById({ deviceId: this.deviceId }).then(res => {
+        const cycle = parseInt(res.data && res.data.calibrationDate)
+        this.calibrationCycle = cycle > 0 ? cycle : 12
+      }).catch(() => {
+        this.calibrationCycle = 12
+      })
+    },
+    // 涓嬫鏍″噯鏃ユ湡 = 鏍″噯鏃ユ湡 + 鏍″噯鍛ㄦ湡锛堟湀锛�
+    getNextCalibrationDate(val) {
+      if (!val) {
+        this.calibrationRecord.nextCalibrationDate = null
+        return
+      }
+      const cycle = parseInt(this.calibrationCycle)
+      const months = cycle > 0 ? cycle : 12
+      this.calibrationRecord.nextCalibrationDate = dayjs(val).add(months, 'month').format('YYYY-MM-DD')
+    },
+    // 鑾峰彇璁惧鏍″噯鍙傛暟锛堟牎鍑嗘潯鐩級
+    async getXmsg() {
+      this.calibrateParamsLoading = true
+      try {
+        await selectDeviceMetric({ deviceId: this.deviceId, type: 'calibrate' }).then(res => {
+          if (res.code == 200) {
+            this.calibrateParams = res.data
+          }
+          this.calibrateParamsLoading = false
+        })
+      } catch (e) {
+        console.log('getXmsg---', e)
+        this.calibrateParamsLoading = false
+      }
+    },
+    addRecord() {
+      this.$refs['calibrationRecord'].validate((valid) => {
+        if (valid) {
+          try {
+            if (this.calibrateParams.some(m => !m.isCalibration)) {
+              this.$message.error('璇烽�夋嫨鏄惁鏍″噯')
+              return
+            }
+            if (!this.calibrateParams.every(m => m.result)) {
+              this.$message.error('璇烽�夋嫨鍒ゅ畾缁撴灉')
+              return
+            }
+            this.addRecordLoading = true
+            // 鍙洖浼犳槑缁嗛渶瑕佺殑瀛楁锛氭簮琛屽甫涓婚敭 id/deviceId 浼氳鐩栧巻鍙叉潯鐩紝creationTime 鏍煎紡涔熶笌鏄庣粏琛ㄤ笉鍏煎
+            const deviceMetricsCopyList = this.calibrateParams.map(item => ({
+              measurementParameter: item.measurementParameter,
+              rangeOfMeasurement: item.rangeOfMeasurement,
+              maxPermissibleError: item.maxPermissibleError,
+              judgmentCriteria: item.judgmentCriteria,
+              createdBy: item.createdBy,
+              isCalibration: item.isCalibration,
+              result: item.result,
+              singleResultStatement: item.singleResultStatement,
+              type: item.type
+            }))
+            // 鍚庣鏃ユ湡瀛楁瑕佹眰 yyyy-MM-dd HH:mm:ss锛屾棩鏈熸帶浠跺彧缁欏埌 yyyy-MM-dd
+            const payload = {
+              ...this.calibrationRecord,
+              deviceId: this.deviceId,
+              createUser: this.nickName,
+              type: 'calibrate',
+              deviceMetricsCopyList
+            }
+            if (payload.calibrationDate && payload.calibrationDate.length === 10) {
+              payload.calibrationDate += ' 00:00:00'
+            }
+            if (payload.nextCalibrationDate && payload.nextCalibrationDate.length === 10) {
+              payload.nextCalibrationDate += ' 00:00:00'
+            }
+            addOrUpdateDeviceMetricRecord(payload).then(res => {
+              if (res.code == 200) {
+                this.$message.success('娣诲姞鎴愬姛')
+                this.visible = false
+                this.$emit('success')
+              }
+              this.addRecordLoading = false
+            }).catch(() => {
+              this.addRecordLoading = false
+            })
+          } catch (e) {
+            console.log('addRecord---', e)
+            this.addRecordLoading = false
+          }
+        } else {
+          this.$message.warning('鏈夊繀濉」鏈~');
+        }
+      })
+    },
+    resetCalibrationRecord() {
+      this.$refs.calibrationRecord.resetFields()
+    },
+    // 涓婁紶闄勪欢
+    handleSuccessUp(response, file) {
+      if (response.code == 200) {
+        // 鍦ㄤ繚瀛樿祴鍊兼柊鏂囦欢
+        this.calibrationRecord.fileName = file.name
+        this.calibrationRecord.systemFileName = response.data
+        this.upLoading = false;
+      } else {
+        this.upLoading = false;
+        this.$message.error(response.message)
+      }
+    },
+    beforeUpload(file) {
+      if (file.size > 1024 * 1024 * 10) {
+        this.$message.error('涓婁紶鏂囦欢涓嶈秴杩�10M');
+        this.$refs.upload.clearFiles()
+        return false;
+      } else {
+        this.upLoading = true;
+        return true;
+      }
+    },
+    onError(err, file, fileList) {
+      this.upLoading = false
+      this.$message.error('涓婁紶澶辫触')
+      this.$refs.upload.clearFiles()
+    },
+    deleteFile() {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎鏂囦欢, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        deleteCNASFile({ fileName: this.calibrationRecord.systemFileName }).then(res => {
+          if (res.code == 200) {
+            this.calibrationRecord.fileName = ''
+            this.calibrationRecord.systemFileName = ''
+            this.$refs.upload.clearFiles()
+            this.$message.success('鍒犻櫎鎴愬姛锛�')
+          }
+        })
+      }).catch((err) => {
+        console.log('err----', err)
+        this.$message({
+          type: 'info',
+          message: '宸插彇娑堝垹闄�'
+        });
+      });
+    },
+  },
+  watch: {
+    visible(newVal) {
+      if (newVal === false) {
+        this.calibrateParams = []
+        this.calibrationRecord = {
+          unitOfMeasure: '', // 璁¢噺鍗曚綅
+          calibrationDate: null, // 鏍″噯鏃ユ湡
+          nextCalibrationDate: null, // 涓嬫鏍″噯鏃ユ湡
+          calculatingApparatus: '', // 璁¢噺鍣ㄥ叿
+          standardRange: '', // 璁¢噺鏍囧噯閲忕▼
+          calibrationStandardUncertainty: '', // 璁¢噺鏍囧噯涓嶇‘瀹氬害
+          byDocument: '', // 渚濇嵁鏂囦欢
+          certificateSerialNumber: '', // 璇佷功缂栧彿
+          status: '', // 鐘舵��
+          remark: '', // 澶囨敞
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+h4 {
+  font-weight: 400;
+  font-size: 16px;
+  display: flex;
+  justify-content: space-between;
+  margin: 10px 0;
+}
+
+h4 .line {
+  display: inline-block;
+  width: 3px;
+  height: 16px;
+  background: var(--el-color-primary);
+  margin-right: 4px;
+}
+</style>
diff --git a/src/views/CNAS/resourceDemand/device/component/check.vue b/src/views/CNAS/resourceDemand/device/component/check.vue
index e9f048c..b6257eb 100644
--- a/src/views/CNAS/resourceDemand/device/component/check.vue
+++ b/src/views/CNAS/resourceDemand/device/component/check.vue
@@ -23,10 +23,13 @@
         </el-table-column>
         <el-table-column label="鏍告煡璇佷功缂栧彿" min-width="150" prop="certificateSerialNumber"></el-table-column>
         <el-table-column label="璇存槑" min-width="150" prop="remark" show-overflow-tooltip></el-table-column>
-        <el-table-column label="鏍告煡鏃ユ湡" min-width="150" prop="calibrationDate"></el-table-column>
-        <el-table-column label="涓嬫鏍告煡鏃ユ湡" min-width="150" prop="nextCalibrationDate"></el-table-column>
+        <el-table-column label="鏍告煡鏃ユ湡" min-width="150" prop="calibrationDate"
+          :formatter="formatDateCell"></el-table-column>
+        <el-table-column label="涓嬫鏍告煡鏃ユ湡" min-width="150" prop="nextCalibrationDate"
+          :formatter="formatDateCell"></el-table-column>
         <el-table-column label="鐧昏浜�" min-width="150" prop="createUser"></el-table-column>
-        <el-table-column label="鐧昏鏃ユ湡" min-width="150" prop="createTime"></el-table-column>
+        <el-table-column label="鐧昏鏃ユ湡" min-width="150" prop="createTime"
+          :formatter="formatDateCell"></el-table-column>
         <el-table-column fixed="right" label="鎿嶄綔" min-width="150">
           <template #default="{ row }">
             <el-button size="small" link type="primary" @click="handleAttachmentClick(row)">闄勪欢</el-button>
@@ -87,7 +90,7 @@
         <el-table-column label="鏈�澶у厑璁歌宸�" prop="maxPermissibleError"></el-table-column>
         <el-table-column label="鍒ゅ畾鏍囧噯" prop="judgmentCriteria"></el-table-column>
         <el-table-column label="鍒涘缓浜�" prop="createdBy"></el-table-column>
-        <el-table-column label="鍒涘缓鏃堕棿" prop="creationTime"></el-table-column>
+        <el-table-column label="鍒涘缓鏃堕棿" prop="creationTime" :formatter="formatDateCell"></el-table-column>
         <el-table-column fixed="right" label="鎿嶄綔">
           <template #default="scope">
             <el-button size="small" link type="primary" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
@@ -250,6 +253,7 @@
 <script>
 import file from '@/utils/file';
 import { mapGetters } from "@/utils/store-compat";
+import { formatListDate } from './dateFormat';
 export default {
   components: {},
   props: {
@@ -340,6 +344,9 @@
     this.getTableList(this.clickNodeVal.value) // 鑾峰彇璁惧鏍告煡鍒楄〃鏁版嵁
   },
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     //鐘舵�佸垽瀹�
     checkRadio() {
       let resultList = this.calibrateParams.map(ele => ele.result)
diff --git a/src/views/CNAS/resourceDemand/device/component/checkRecord.vue b/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
index 5c7eca4..3fe2c2f 100644
--- a/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
+++ b/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
@@ -1,7 +1,7 @@
 <template>
   <div>
     <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible"
-      title="浠櫒璁惧鏈熼棿鏍告煡姣斿璁板綍琛�" width="80%" @close="resetForm">
+      title="浠櫒璁惧鏈熼棿鏍告煡璁板綍琛�" width="80%" @close="resetForm">
       <el-steps :active="currentStep" align-center finish-status="success">
         <el-step title="濉啓璁惧鏍告煡瀵规瘮璁板綍"></el-step>
         <el-step title="瀹℃牳"></el-step>
@@ -10,9 +10,9 @@
         <el-col :span="8">
           <div class="form-item">
             <span style="width: 110px">浠櫒鍚嶇О锛�</span>
-            <el-select v-model="form.deviceName" :disabled="currentStep !== 0" class="table_input" clearable filterable
-              placeholder="璁惧鍚嶇О" size="small" style="width:200px" @change="(val) => changeMachineName(val)">
-              <el-option v-for="item in equipOptions" :key="item.value" :label="item.label" :value="item.label">
+            <el-select v-model="selectedDeviceId" :disabled="currentStep !== 0" class="table_input" clearable filterable
+              placeholder="璁惧鍚嶇О" size="small" style="width:200px" @change="changeMachineName">
+              <el-option v-for="item in equipOptions" :key="item.id" :label="item.label" :value="item.id">
                 {{ item.label + '-' + item.value }}
               </el-option>
             </el-select>
@@ -84,11 +84,11 @@
           </div>
         </el-col>
       </el-row>
-      <el-button size="small" style="margin: 10px 0" type="primary" @click="addRow">娣诲姞</el-button>
+      <el-button v-if="currentStep === 0" size="small" style="margin: 10px 0" type="primary" @click="addRow">娣诲姞</el-button>
       <el-table :data="recordDetailList" height="300" style="width: 100%" border>
         <el-table-column label="娴嬭瘯鐐�" min-width="130" prop="testPoint">
           <template #default="scope">
-            <el-input v-model="scope.row.testPoint" clearable size="small"></el-input>
+            <el-input v-model="scope.row.testPoint" :disabled="currentStep !== 0" clearable size="small"></el-input>
           </template>
         </el-table-column>
         <el-table-column min-width="180">
@@ -283,6 +283,7 @@
         { label: '鐩稿鍋忓樊', value: 2 },
       ],
       equipOptions: [],
+      selectedDeviceId: '',
       submitFormLoading: false,
       userList: [],
       reviewUserId: '',
@@ -299,6 +300,7 @@
   methods: {
     openDialog(row) {
       this.dialogVisible = true
+      this.selectedDeviceId = ''
       this.form.planDetailsId = row.planDetailsId
       this.checkChargerUserId = row.checkChargerUserId
       this.getEquipOptions()
@@ -321,19 +323,38 @@
             this.currentStep = 2
           }
           this.reviewUserId = this.form.reviewUserId
+          this.matchDeviceOption()
           this.$nextTick(() => {
             this.draftRestore('checkRecordForm', 'form', this.form.planDetailsId, 'dialogVisible')
             this.draftRestore('checkRecordRows', 'recordDetailList', this.form.planDetailsId, 'dialogVisible')
+            // 鑽夌閲屽彲鑳芥敼杩囪澶囷紝鎭㈠鍚庨噸鏂板尮閰嶄笅鎷夐�変腑椤�
+            this.matchDeviceOption()
           })
         }
       }).catch(error => {
         console.error(error)
       })
     },
-    // 璧嬪�间华鍣ㄧ紪鍙�
+    // 鎸夎澶� id 鍥炲~鍚嶇О鍜岀紪鍙凤紝閬垮厤鍚屽悕璁惧閫夐敊
     changeMachineName(value) {
-      const index = this.equipOptions.findIndex(item => item.deviceName === value)
-      this.form.deviceNumber = this.equipOptions[index].managementNumber
+      const item = this.equipOptions.find(device => device.id === value)
+      if (item) {
+        this.form.deviceName = item.deviceName
+        this.form.deviceNumber = item.managementNumber
+      } else {
+        this.form.deviceName = ''
+        this.form.deviceNumber = ''
+      }
+    },
+    // 鍘嗗彶璁板綍娌℃湁 deviceId锛屾寜鍚嶇О+缂栧彿鍙嶆煡涓嬫媺閫夐」
+    matchDeviceOption() {
+      if (!this.equipOptions.length || !this.form.deviceName) {
+        return
+      }
+      const match = this.form.deviceNumber
+        ? this.equipOptions.find(item => item.deviceName === this.form.deviceName && item.managementNumber === this.form.deviceNumber)
+        : this.equipOptions.find(item => item.deviceName === this.form.deviceName)
+      this.selectedDeviceId = match ? match.id : ''
     },
     addRow() {
       this.recordDetailList.push({ testPoint: '' })
@@ -390,6 +411,7 @@
             m.id = m.id
             return m
           })
+          this.matchDeviceOption()
         }
       }).catch(error => {
         console.error(error)
diff --git a/src/views/CNAS/resourceDemand/device/component/dateFormat.js b/src/views/CNAS/resourceDemand/device/component/dateFormat.js
new file mode 100644
index 0000000..36065ed
--- /dev/null
+++ b/src/views/CNAS/resourceDemand/device/component/dateFormat.js
@@ -0,0 +1,26 @@
+import dayjs from 'dayjs'
+
+// 鍒楄〃鏃ユ湡缁熶竴鏄剧ず锛氱函鏃ユ湡鍙樉绀哄勾鏈堟棩锛屾椂闂村幓鎺� ISO 鐨� T锛屽彧淇濈暀鍒板垎閽�
+export function formatListDate(value) {
+  if (value === null || value === undefined || value === '') {
+    return value
+  }
+  const str = String(value)
+  if (/^\d{4}-\d{2}-\d{2}$/.test(str)) {
+    return str
+  }
+  if (/T00:00:00(\.\d+)?$/.test(str) || / 00:00:00$/.test(str)) {
+    return str.slice(0, 10)
+  }
+  const date = dayjs(str)
+  return date.isValid() ? date.format('YYYY-MM-DD HH:mm') : str
+}
+
+// 绾棩鏈熺粺涓�鏄剧ず yyyy-MM-dd锛屽拷鐣ュ彲鑳藉甫鍑虹殑鏃堕棿閮ㄥ垎
+export function formatDateOnly(value) {
+  if (value === null || value === undefined || value === '') {
+    return value
+  }
+  const date = dayjs(String(value).replace(/\//g, '-'))
+  return date.isValid() ? date.format('YYYY-MM-DD') : formatListDate(value)
+}
diff --git a/src/views/CNAS/resourceDemand/device/component/deviceOverview.vue b/src/views/CNAS/resourceDemand/device/component/deviceOverview.vue
index 76e7268..88aa48d 100644
--- a/src/views/CNAS/resourceDemand/device/component/deviceOverview.vue
+++ b/src/views/CNAS/resourceDemand/device/component/deviceOverview.vue
@@ -29,7 +29,7 @@
         v-if="list.length > 0 || loading">
         <ul class="card">
           <li v-for="(m, i) in list" :key="i">
-            <el-image class="img" :src="javaApi + '/img/' + m.imageUpload">
+            <el-image v-if="m.imageUpload" class="img" :src="javaApi + '/img/' + m.imageUpload">
               <template #error><div  class="image-error" style="width: 88px;
             height: 88px;
             border-radius: 16px;
@@ -40,6 +40,15 @@
                 <lims-icon name="el-icon-picture-outline" style="font-size:20px;color:var(--lims-text-2);"></lims-icon>
               </div></template>
             </el-image>
+            <div v-else class="image-error" style="width: 88px;
+            height: 88px;
+            border-radius: 16px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            border: 1px solid var(--lims-divider);margin-right: 10px;">
+              <lims-icon name="el-icon-picture-outline" style="font-size:20px;color:var(--lims-text-2);"></lims-icon>
+            </div>
             <div class="list-left">
               <div class="list-left-info">
                 <span class="label" style="white-space: nowrap;">璁惧鍚嶇О锛�</span>
@@ -99,6 +108,7 @@
   selectDeviceParameter,
   downloadDeviceImportTemplate,
 } from '@/api/cnas/resourceDemand/device.js'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   props: {
     clickNodeVal: {
@@ -146,8 +156,8 @@
   methods: {
     downloadTemplate() {
       downloadDeviceImportTemplate().then(res => {
-        this.$download.saveAs(new Blob([res]), '璁惧瀵煎叆妯℃澘.xlsx')
-      })
+        saveBlobOrShowError(res, '璁惧瀵煎叆妯℃澘.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+      }).catch(() => { })
     },
     submitImport() {
       if (!this.$refs.deviceUpload.uploadFiles.length) {
@@ -252,6 +262,11 @@
           }
         }
         this.loading = false
+      }).catch(() => {
+        // 娓呮帀鏈〉鍗犱綅锛屽け璐ュ悗鍙敤鏌ヨ/閲嶇疆閲嶆柊鍔犺浇
+        delete this.keyMap[key]
+        this.loading = false
+        this.finishLoding = true
       })
     },
     refresh() {
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentAcceptance.vue b/src/views/CNAS/resourceDemand/device/component/equipmentAcceptance.vue
index e20c4e3..3b01892 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentAcceptance.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentAcceptance.vue
@@ -26,7 +26,7 @@
             </template>
           </el-table-column>
         </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
+        <el-pagination :current-page="pagination1.current" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
           :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper" background
           @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
         </el-pagination>
@@ -45,7 +45,7 @@
       </div>
       <div>
         <limsTable ref="yearTable" :column="columnData" :height="'calc(100vh - 30em)'" :highlightCurrentRow="true"
-          :table-data="tableData" :table-loading="tableLoading" style="margin-top: 0.5em;" :page="pagination1">
+          :table-data="tableData" :table-loading="tableLoading" style="margin-top: 0.5em;" :page="filePage">
         </limsTable>
       </div>
     </el-dialog>
@@ -67,6 +67,7 @@
   exportDeviceAcceptance,
   delDeviceAcceptance,
 } from '@/api/cnas/resourceDemand/device.js'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   name: "equipment-acceptance",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -82,6 +83,11 @@
     // 杩欓噷瀛樻斁鏁版嵁
     return {
       pagination1: {
+        size: 10,
+        current: 1,
+        total: 0,
+      },
+      filePage: {
         size: 10,
         current: 1,
         total: 0,
@@ -171,6 +177,7 @@
     record(row) {
       this.filesDialogVisible = true
       this.acceptanceId = row.acceptanceId
+      this.filePage.current = 1
       this.searchTableList()
     },
     // 鏌ヨ闄勪欢鍒楄〃
@@ -178,7 +185,8 @@
       this.tableLoading = true
       getDeviceAcceptanceFileList({ acceptanceId: this.acceptanceId }).then(res => {
         this.tableLoading = false
-        this.tableData = res.data
+        this.tableData = res.data || []
+        this.filePage.total = this.tableData.length
       }).catch(err => {
         this.tableLoading = false
         console.log('err---', err);
@@ -197,7 +205,14 @@
     },
     // 涓嬭浇
     upload(row) {
-      this.$download.saveAs(row.fileUrl, row.fileName)
+      if (!row.fileUrl) {
+        this.$message.warning('鏈笂浼犳枃浠讹紒')
+        return
+      }
+      // 鍥剧墖瀛� /img/锛屽叾浠栨枃妗e瓨 /word/
+      const isImage = /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(row.fileUrl)
+      const url = this.javaApi + (isImage ? '/img/' : '/word/') + row.fileUrl
+      this.$download.saveAs(url, row.fileName || row.fileUrl)
     },
     // 鍒犻櫎
     delete(row) {
@@ -239,10 +254,11 @@
       this.$refs.upload.clearFiles()
     },
     handleSuccessUp(response,) {
-      this.upLoading = false;
       if (response.code == 200) {
         this.$message.success('涓婁紶鎴愬姛');
         this.searchTableList()
+      } else {
+        this.$message.error(response.message || response.msg || '涓婁紶澶辫触')
       }
     },
     closeFilesLook() {
@@ -263,8 +279,9 @@
       this.outLoading = true
       exportDeviceAcceptance({ acceptanceId: id }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '璁惧楠屾敹.doc')
+        saveBlobOrShowError(res, '璁惧楠屾敹.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     // 鍒犻櫎
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentAccident.vue b/src/views/CNAS/resourceDemand/device/component/equipmentAccident.vue
index 1c6d407..5ed5d1a 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentAccident.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentAccident.vue
@@ -15,13 +15,14 @@
           <!--          <el-table-column label="浠櫒鍚嶇О" min-width="150" prop="unitName"></el-table-column>-->
           <!--          <el-table-column label="鍨嬪彿" min-width="100" prop="model"></el-table-column>-->
           <el-table-column label="鍦扮偣" min-width="150" prop="address"></el-table-column>
-          <el-table-column label="鏃ユ湡" min-width="180" prop="accidentDate"></el-table-column>
+          <el-table-column label="鏃ユ湡" min-width="180" prop="accidentDate"
+            :formatter="formatDateCell"></el-table-column>
           <el-table-column label="浜嬫晠鎯呭喌" min-width="180" prop="descriptionOfAccident"
             show-overflow-tooltip></el-table-column>
           <!-- 鎿嶄綔鎸夐挳 -->
           <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="120">
             <template #default="scope">
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="primary"
+              <el-button :disabled="scope.row.isFinish === 1" size="small" link type="primary"
                 @click="handleForm(scope.row.accidentReportId)">鎿嶄綔</el-button>
               <el-button size="small" link type="primary" @click="handleDownOne(scope.row.accidentReportId)">瀵煎嚭</el-button>
               <el-button :disabled="scope.row.isFinish === 1" size="small" link type="danger"
@@ -29,7 +30,7 @@
             </template>
           </el-table-column>
         </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
+        <el-pagination :current-page="pagination1.current" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
           :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper" background
           @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
         </el-pagination>
@@ -46,6 +47,8 @@
   exportDeviceAccidentReport,
   delDeviceAccidentReport,
 } from '@/api/cnas/resourceDemand/device.js'
+import { formatListDate } from './dateFormat'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   name: "equipment-accident",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -75,6 +78,9 @@
   },
   // 鏂规硶闆嗗悎
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     // 鏌ヨ
     getYearTableDetailData(deviceId) {
       this.yearTableDetailDataLoading = true
@@ -117,8 +123,9 @@
       this.outLoading = true
       exportDeviceAccidentReport({ accidentReportId: id }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '浠櫒璁惧浜嬫晠鎶ュ憡鍗�.doc')
+        saveBlobOrShowError(res, '浠櫒璁惧浜嬫晠鎶ュ憡鍗�.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     // 鍒犻櫎
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentCalibrationPlan.vue b/src/views/CNAS/resourceDemand/device/component/equipmentCalibrationPlan.vue
index 1bb40cf..58862d8 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentCalibrationPlan.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentCalibrationPlan.vue
@@ -1,114 +1,84 @@
 <template>
   <!--  璁惧鏍″噯璁″垝-->
   <div>
-    <div>
-      <div style="margin: 10px 0;display: flex;align-items: center;justify-content: space-between;">
-        <div class="title">
-          <span style="font-weight: bold">骞村害璁″垝琛�</span>
+    <div style="margin: 10px 0 14px;">
+      <div class="plan-top">
+        <div class="plan-top-left">
+          <span class="title" style="margin-bottom: 0;">{{ planInfo.planName || (planYear + '骞村害璁惧鏍″噯璁″垝') }}</span>
+          <el-select v-model="planYear" size="small" style="width: 110px; margin-left: 16px;" @change="handleYearChange">
+            <el-option v-for="y in yearOptions" :key="y" :label="y" :value="y"></el-option>
+          </el-select>
         </div>
         <div>
-          <el-button size="small" type="primary" @click="getYearTableData">鍒锋柊</el-button>
-          <el-button size="small" type="primary" @click="addYearPlan('add')">鏂板</el-button>
-          <!--          <el-button size="small" type="primary" @click="record">瀵煎叆</el-button>-->
+          <el-button size="small" type="primary" @click="loadPlan">鍒锋柊</el-button>
+          <el-button size="small" type="primary" :disabled="planInfo.ratifyStatus === 1"
+            @click="tellApprove">鎵瑰噯閫氱煡</el-button>
+          <el-button size="small" type="primary"
+            :disabled="planInfo.ratifyStatus === 1 || userId != planInfo.ratifyUserId" @click="handleApprove">鎵瑰噯</el-button>
+          <el-button size="small" type="primary" @click="downLoadPost">瀵煎嚭</el-button>
         </div>
       </div>
+      <div class="plan-info-bar">
+        <span>缂栧埗浜猴細{{ planInfo.writeName || '鈥�' }}</span>
+        <span>缂栧埗鏃ユ湡锛歿{ planInfo.writeTimeStr || '鈥�' }}</span>
+        <span v-if="planInfo.ratifyStatus === 1">鎵瑰噯鐘舵�侊細<el-tag type="success">鎵瑰噯</el-tag></span>
+        <span v-else-if="planInfo.ratifyStatus === 0">鎵瑰噯鐘舵�侊細<el-tag type="danger">涓嶆壒鍑�</el-tag></span>
+        <span v-if="planInfo.ratifyRemark">鎵瑰噯鍐呭锛歿{ planInfo.ratifyRemark }}</span>
+        <span v-if="isRatified && planInfo.ratifyName">鎵瑰噯浜猴細{{ planInfo.ratifyName }}</span>
+        <span v-if="isRatified && planInfo.ratifyTimeStr">鎵瑰噯鏃堕棿锛歿{ planInfo.ratifyTimeStr }}</span>
+      </div>
+    </div>
+    <div class="search">
       <div>
-        <el-table ref="yearTable" v-loading="yearTableDataLoading"
-                  :data="yearTableData" height="calc(60vh - 16em)"
- border
-                  highlight-current-row @current-change="currentChange">
-          <!-- 琛ㄦ牸鍒� -->
-          <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
-            width="70"></el-table-column>
-          <el-table-column label="骞翠唤" min-width="80" prop="planYear"></el-table-column>
-          <el-table-column label="璁″垝鍚嶇О" min-width="180" prop="planName" show-overflow-tooltip></el-table-column>
-          <el-table-column label="缂栧埗浜�" min-width="100" prop="writeName"></el-table-column>
-          <el-table-column label="缂栧埗鏃ユ湡" min-width="160" prop="writeTime"></el-table-column>
-          <el-table-column label="鎵瑰噯鐘舵��" min-width="100" prop="ratifyStatus">
-            <template #default="scope">
-              <el-tag v-if="scope.row.ratifyStatus === 1" type="success">鎵瑰噯</el-tag>
-              <el-tag v-if="scope.row.ratifyStatus === 0" type="danger">涓嶆壒鍑�</el-tag>
-            </template>
-          </el-table-column>
-          <el-table-column label="鎵瑰噯鍐呭" min-width="150" prop="ratifyRemark"></el-table-column>
-          <el-table-column label="鎵瑰噯浜�" min-width="100" prop="ratifyName"></el-table-column>
-          <el-table-column label="鎵瑰噯鏃堕棿" min-width="150" prop="ratifyTime"></el-table-column>
-          <!-- 鎿嶄綔鎸夐挳 -->
-          <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="240">
-            <template #default="scope">
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="primary"
-                @click="addYearPlan('edit', scope.row)">缂栬緫</el-button>
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="primary"
-                @click="tellApprove(scope.row.planId)">鎵瑰噯閫氱煡</el-button>
-              <el-button :disabled="scope.row.ratifyStatus === 1 || userId != scope.row.ratifyUserId" size="small"
-                link type="primary" @click="handleApprove(scope.row.planId)">鎵瑰噯</el-button>
-              <el-button size="small" link type="primary" @click="downLoadPost(scope.row.planId)">瀵煎嚭</el-button>
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="danger"
-                @click="deleteFun(scope.row.planId)">鍒犻櫎</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-        <el-pagination :current-page="1" :page-size="pagination.size" :page-sizes="[10, 20, 30, 50, 100]"
-                       background :total="pagination.total" layout="->,total, sizes, prev, pager, next, jumper"
-                       @size-change="handleSizeChange" @current-change="handleCurrentChange">
-        </el-pagination>
+        <el-form :model="searchForm" ref="searchForm" size="small" :inline="true">
+          <el-form-item label="璁惧鍚嶇О鍙婂瀷鍙�" prop="deviceName">
+            <el-input v-model="searchForm.deviceName" clearable @keyup.enter="handleQuery"
+              size="small"></el-input>
+          </el-form-item>
+          <el-form-item label="浠櫒缂栧彿" prop="deviceNumber">
+            <el-input v-model="searchForm.deviceNumber" @keyup.enter="handleQuery" clearable
+              size="small"></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" size="small" @click="handleQuery">鏌ヨ</el-button>
+            <el-button size="small" @click="reset">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
       </div>
     </div>
     <div>
-      <div class="title">
-        <span style="font-weight: bold">骞村害璁″垝鏄庣粏琛�</span>
-      </div>
-      <div class="search">
-        <div>
-          <el-form :model="searchForm" ref="searchForm" size="small" :inline="true">
-            <el-form-item label="璁惧鍚嶇О鍙婂瀷鍙�" prop="deviceName">
-              <el-input v-model="searchForm.deviceName" clearable
-                        @keyup.enter="getYearTableDetailData(currentRow)" size="small"></el-input>
-            </el-form-item>
-            <el-form-item label="浠櫒缂栧彿" prop="deviceNumber">
-              <el-input v-model="searchForm.deviceNumber"
-                        @keyup.enter="getYearTableDetailData(currentRow)" clearable size="small"></el-input>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" size="small" @click="getYearTableDetailData(currentRow)">鏌ヨ</el-button>
-              <el-button size="small" @click="reset">閲嶇疆</el-button>
-            </el-form-item>
-          </el-form>
-        </div>
-        <div>
-          <el-button size="small" type="primary" @click="handleForm('add')">鏂板</el-button>
-        </div>
-      </div>
-      <div>
-        <el-table ref="yearTableDetailData" v-loading="yearTableDetailDataLoading" :data="yearTableDetailData"
- border
-                  :height="'calc(100vh - 34em)'" style="width: 100% ;">
-          <!-- 琛ㄦ牸鍒� -->
-          <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
-            width="70"></el-table-column>
-          <el-table-column label="璁惧鍚嶇О鍙婂瀷鍙�" min-width="180" prop="deviceName" show-overflow-tooltip></el-table-column>
-          <el-table-column label="璁惧鏁伴噺" min-width="180" prop="deviceAmount"></el-table-column>
-          <el-table-column label="浠櫒缂栧彿" min-width="150" prop="deviceNumber"></el-table-column>
-          <el-table-column label="妫�瀹氬崟浣�" min-width="150" prop="verificationUnit"> </el-table-column>
-          <el-table-column label="妫�瀹氬懆鏈�" min-width="150" prop="verificationCycles"></el-table-column>
-          <el-table-column label="鏈�杩戞瀹氭椂闂�" min-width="150" prop="lastDate"></el-table-column>
-          <el-table-column label="鏈勾璁″垝鏍″噯鏃堕棿" min-width="150" prop="planDate"></el-table-column>
-          <el-table-column label="澶囨敞" min-width="150" prop="remark"></el-table-column>
-          <!-- 鎿嶄綔鎸夐挳 -->
-          <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="140">
-            <template #default="scope">
-              <el-button size="small" link type="primary" @click="handleForm('edit', scope.row)">缂栬緫</el-button>
-              <el-button size="small" link type="primary" @click="handleForm('view', scope.row)">鏌ョ湅</el-button>
-              <el-button size="small" link type="danger"
-                @click="deleteFun1(scope.row.planDetailId)">鍒犻櫎</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
-                       background :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper"
-                       @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
-        </el-pagination>
-      </div>
+      <el-table ref="yearTableDetailData" v-loading="yearTableDetailDataLoading" :data="yearTableDetailData" border
+        :row-class-name="tableRowClassName" :height="'calc(100vh - 29em)'" style="width: 100% ;">
+        <!-- 琛ㄦ牸鍒� -->
+        <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
+          width="70"></el-table-column>
+        <el-table-column label="璁惧鍚嶇О鍙婂瀷鍙�" min-width="180" prop="deviceName" show-overflow-tooltip></el-table-column>
+        <el-table-column label="璁惧鏁伴噺" min-width="90" prop="deviceAmount"></el-table-column>
+        <el-table-column label="浠櫒缂栧彿" min-width="150" prop="deviceNumber"></el-table-column>
+        <el-table-column label="妫�瀹氬崟浣�" min-width="150" prop="verificationUnit"> </el-table-column>
+        <el-table-column label="妫�瀹氬懆鏈�" min-width="100" prop="verificationCycles"></el-table-column>
+        <el-table-column label="鏈�杩戞瀹氭椂闂�" min-width="130" prop="lastDate"
+          :formatter="formatDateCell"></el-table-column>
+        <el-table-column label="鏈勾璁″垝鏍″噯鏃堕棿" min-width="130" prop="planDate"
+          :formatter="formatDateCell"></el-table-column>
+        <el-table-column label="澶囨敞" min-width="130" prop="remark"></el-table-column>
+        <!-- 鎿嶄綔鎸夐挳 -->
+        <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="210">
+          <template #default="scope">
+            <el-button size="small" link type="primary" :disabled="!scope.row.deviceId"
+              @click="handleExecute(scope.row)">鎵ц</el-button>
+            <el-button size="small" link type="primary" :disabled="planInfo.ratifyStatus === 1"
+              @click="handleForm('edit', scope.row)">缂栬緫</el-button>
+            <el-button size="small" link type="primary" @click="handleForm('view', scope.row)">鏌ョ湅</el-button>
+            <el-button size="small" link type="danger" :disabled="planInfo.ratifyStatus === 1"
+              @click="deleteFun1(scope.row.planDetailId)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination :current-page="pagination1.current" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
+        background :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
+      </el-pagination>
     </div>
     <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible" title="璁惧鏍″噯璁″垝"
       width="80%" @close="resetForm">
@@ -162,7 +132,7 @@
           </el-form-item>
         </el-col>
       </el-form>
-      <template #footer><span  class="dialog-footer">
+      <template #footer><span class="dialog-footer">
         <el-button @click="resetForm">鍙� 娑�</el-button>
         <el-button :loading="submitFormLoading" type="primary" @click="submitForm" v-if="operationType !== 'view'">纭�
           璁�</el-button>
@@ -173,7 +143,7 @@
         鎵瑰噯澶囨敞锛�
         <el-input v-model="ratifyRemark" type="textarea"></el-input>
       </span>
-      <template #footer><span  class="dialog-footer">
+      <template #footer><span class="dialog-footer">
         <el-button :loading="approvalLoading" @click="handleApproval(0)">涓嶆壒鍑�</el-button>
         <el-button :loading="approvalLoading" type="primary" @click="handleApproval(1)">鎵� 鍑�</el-button>
       </span></template>
@@ -186,53 +156,36 @@
           </el-option>
         </el-select>
       </span>
-      <template #footer><span  class="dialog-footer">
+      <template #footer><span class="dialog-footer">
         <el-button :loading="notificationLoading" @click="closeNotificationDia">鍙� 娑�</el-button>
         <el-button :loading="notificationLoading" type="primary" @click="notification">鎻� 浜�</el-button>
       </span></template>
     </el-dialog>
-    <!--涓婁紶鎶ュ憡-->
-    <el-dialog v-model="uploadDia" title="鏁版嵁瀵煎叆" width="500px">
-      骞翠唤锛�
-      <el-date-picker v-model="planYear" type="year" value-format="YYYY" clearable format="YYYY" placeholder="閫夋嫨骞�">
-      </el-date-picker>
-      <div style="margin: 0 auto;">
-        <el-upload ref="upload1" :action="action" :auto-upload="false" :file-list="fileList" :headers="uploadHeader"
-          :limit="1" accept='.doc,.docx' :on-change="beforeUpload" :on-error="onError" :on-success="handleSuccessUp"
-          drag name="file">
-          <lims-icon name="el-icon-upload"></lims-icon>
-          <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
-        </el-upload>
-      </div>
-      <template #footer><span  class="dialog-footer">
-        <el-button @click="uploadDia = false">鍙� 娑�</el-button>
-        <el-button :loading="uploading" type="primary" @click="submitUpload()">涓� 浼�</el-button>
-      </span></template>
-    </el-dialog>
-    <add-year-plan-dia v-if="addYearPlanDia" ref="addYearPlanDia" @closeDia="closeDia"></add-year-plan-dia>
+    <!-- 娣诲姞/鏌ョ湅鏍″噯璁板綍寮圭獥 -->
+    <calibration-record-dia ref="calibrationRecordDia" @success="getYearTableDetailData"></calibration-record-dia>
   </div>
 </template>
 
 <script>
-import AddYearPlanDia from "./addYearPlanDia.vue";
-import AddVerificationYearPlanDia from "./addVerificationYearPlanDia.vue";
+import CalibrationRecordDia from "./calibrationRecordDia.vue";
 import {
   pageDeviceCalibrationPlan,
+  getCalibrationPlanByYear,
   submiatRatifyDeviceCalibrationPlan,
   exportDeviceCalibrationPlanDetail,
-  delDeviceCalibrationPlan,
   delDeviceCalibrationPlanDetail,
   pageDeviceCalibrationPlanDetail,
-  addDeviceCalibrationPlanDetail,
   updateDeviceCalibrationPlanDetail,
   ratifyDeviceCalibrationPlan,
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/performance/class";
 import { mapGetters } from "@/utils/store-compat";
+import { formatDateOnly } from './dateFormat'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   name: "equipment-calibration-plan",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
-  components: { AddVerificationYearPlanDia, AddYearPlanDia },
+  components: { CalibrationRecordDia },
   props: {
     clickNodeVal: {
       type: Object,
@@ -244,18 +197,15 @@
   data() {
     // 杩欓噷瀛樻斁鏁版嵁
     return {
+      planYear: '',
+      yearOptions: [],
+      planInfo: {},
       dialogVisible: false,
       searchForm: {
         deviceName: '',
         deviceNumber: '',
       },
-      yearTableData: [],
       yearTableDetailData: [],
-      pagination: {
-        size: 10,
-        current: 1,
-        total: 0,
-      },
       pagination1: {
         size: 10,
         current: 1,
@@ -278,66 +228,165 @@
         deviceNumber: [{ required: true, message: '璇峰~鍐欎华鍣ㄧ紪鍙�', trigger: 'blur' }],
         planDate: [{ required: true, message: '璇烽�夋嫨鏃ユ湡', trigger: 'change' }],
       },
-      yearTableDataLoading: false,
       yearTableDetailDataLoading: false,
-      currentRow: {},
       approvalDialog: false,
       approvalLoading: false,
       submitFormLoading: false,
       ratifyRemark: '',
       currentRowId: '',
-      uploadDia: false,
-      uploading: false,
-      addYearPlanDia: false,
-      fileList: [],
-      planYear: '',
       responsibleOptions: [],
       notificationDia: false,
       notificationLoading: false,
       ratifyUserId: '',
-      planId: ''
     }
   },
   mounted() {
-    this.getYearTableData()
+    this.loadYearOptions()
   },
   // 鏂规硶闆嗗悎
   methods: {
-    // 鏌ヨ骞村害璁″垝琛�
-    getYearTableData() {
-      this.yearTableDataLoading = true
+    // 骞翠唤涓嬫媺閫夐」锛氬凡鏈夎鍒掑勾浠� + 褰撳墠骞翠唤
+    loadYearOptions() {
       pageDeviceCalibrationPlan({
         current: 1,
         size: 99,
       }).then(res => {
+        let years = []
         if (res.code == 200) {
-          this.yearTableData = res.data.records
-          this.pagination.total = res.data.total
-          if (this.yearTableData.length > 0) {
-            this.currentRow = this.yearTableData[0]
-            this.$refs.yearTable.setCurrentRow(this.currentRow)
-          }
+          years = (res.data.records || []).map(r => r.planYear).filter(Boolean)
         }
-        this.yearTableDataLoading = false
-      }).catch(err => {
-        this.yearTableDataLoading = false
+        const currentYear = String(new Date().getFullYear())
+        if (years.indexOf(currentYear) === -1) {
+          years.push(currentYear)
+        }
+        this.yearOptions = [...new Set(years)].sort((a, b) => b.localeCompare(a))
+        this.planYear = currentYear
+        this.loadPlan()
       })
     },
-    // 鍒嗛〉
-    handleSizeChange(val) {
-      this.pagination.size = val
-      this.getYearTableData()
+    // 鍒囨崲骞翠唤
+    handleYearChange() {
+      this.pagination1.current = 1
+      this.loadPlan()
+    },
+    // 鏌ヨ骞翠唤璁″垝锛堜笉瀛樺湪鑷姩鍒涘缓骞惰ˉ鍏ㄥ埌鐐规槑缁嗭級锛岄殢鍚庡埛鏂版槑缁�
+    loadPlan() {
+      getCalibrationPlanByYear({ planYear: this.planYear }).then(res => {
+        if (res.code == 200) {
+          this.planInfo = res.data || {}
+        }
+        this.getYearTableDetailData()
+      }).catch(() => {
+        this.planInfo = {}
+        this.yearTableDetailData = []
+        this.pagination1.total = 0
+        this.yearTableDetailDataLoading = false
+      })
+    },
+    // 鏌ヨ鏉′欢鍙樺寲鍚庝粠绗竴椤靛紑濮嬫煡
+    handleQuery() {
+      this.pagination1.current = 1
+      this.getYearTableDetailData()
+    },
+    // 鏄庣粏-鏌ヨ
+    getYearTableDetailData() {
+      if (!this.planInfo.planId) {
+        return
+      }
+      this.yearTableDetailDataLoading = true
+      pageDeviceCalibrationPlanDetail({
+        current: this.pagination1.current,
+        size: this.pagination1.size,
+        planId: this.planInfo.planId,
+        deviceName: this.searchForm.deviceName,
+        deviceNumber: this.searchForm.deviceNumber,
+      }).then(res => {
+        if (res.code == 200) {
+          this.yearTableDetailData = res.data.records
+          this.pagination1.total = res.data.total
+        }
+        this.yearTableDetailDataLoading = false
+      }).catch(err => {
+        this.yearTableDetailDataLoading = false
+      })
+    },
+    formatDateCell(row, column, cellValue) {
+      return formatDateOnly(cellValue)
+    },
+    // 鍒扮偣闇�鏍″噯鐨勮鏍囩孩
+    tableRowClassName({ row }) {
+      return row.redFlag === 1 ? 'red-row' : ''
+    },
+    reset() {
+      this.searchForm = {
+        deviceName: '',
+        deviceNumber: '',
+      }
+      this.pagination1.current = 1
+      this.getYearTableDetailData()
     },
     // 鍒嗛〉
-    handleCurrentChange(val) {
-      this.pagination.current = val
-      this.getYearTableData()
+    handleSizeChange1(val) {
+      this.pagination1.size = val
+      this.getYearTableDetailData()
+    },
+    // 鍒嗛〉
+    handleCurrentChange1(val) {
+      this.pagination1.current = val
+      this.getYearTableDetailData()
+    },
+    // 鎵ц锛氭墦寮�鏍″噯璁板綍寮圭獥褰曞叆
+    handleExecute(row) {
+      this.$refs.calibrationRecordDia.open(row.deviceId, 'add')
+    },
+    // 鎵撳紑鏄庣粏寮规
+    handleForm(type, row) {
+      this.operationType = type
+      this.dialogVisible = true
+      this.$nextTick(() => {
+        this.form = this.HaveJson(row)
+      })
+    },
+    // 鎻愪氦琛ㄥ崟
+    submitForm() {
+      this.$refs.modelForm.validate(valid => {
+        if (valid) {
+          this.submitFormLoading = true
+          updateDeviceCalibrationPlanDetail(this.form).then(res => {
+            if (res.code == 200) {
+              this.$message.success('淇敼鎴愬姛')
+              this.dialogVisible = false
+              this.getYearTableDetailData()
+            }
+            this.submitFormLoading = false
+          }).catch(err => {
+            this.submitFormLoading = false
+          })
+        }
+      })
+    },
+    // 鏄庣粏-鍒犻櫎
+    deleteFun1(id) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        delDeviceCalibrationPlanDetail({ planDetailsId: id }).then(res => {
+          this.$message.success('鍒犻櫎鎴愬姛锛�');
+          this.getYearTableDetailData()
+        });
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '宸插彇娑堝垹闄�'
+        });
+      });
     },
     // 鎵撳紑鎻愪氦鎵瑰噯寮规
-    tellApprove(planId) {
+    tellApprove() {
       this.getUserList()
       this.notificationDia = true
-      this.planId = planId
     },
     // 鍏抽棴鎻愪氦鎵瑰噯寮规
     closeNotificationDia() {
@@ -353,184 +402,23 @@
       this.notificationLoading = true
       submiatRatifyDeviceCalibrationPlan({
         ratifyUserId: this.ratifyUserId,
-        planId: this.planId,
+        planId: this.planInfo.planId,
       }).then(res => {
         this.notificationLoading = false
         if (res.code == 200) {
           this.closeNotificationDia()
-          this.getYearTableData()
+          this.loadPlan()
         }
       }).catch(err => {
         this.notificationLoading = false
       })
     },
-    // 骞村害璁″垝琛�-鎵瑰噯
-    handleApprove(id) {
-      this.currentRowId = id
+    // 鎵瑰噯
+    handleApprove() {
+      this.currentRowId = this.planInfo.planId
       this.approvalDialog = true
     },
-    // 骞村害璁″垝琛�-瀵煎嚭
-    downLoadPost(planId) {
-      exportDeviceCalibrationPlanDetail({ planId }).then(res => {
-        const blob = new Blob([res], { type: 'application/msword' });
-        this.$download.saveAs(blob, '璁惧鏍″噯璁″垝.docx')
-      })
-    },
-    // 骞村害璁″垝琛�-鍒犻櫎
-    deleteFun(id) {
-      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
-        confirmButtonText: '纭畾',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning'
-      }).then(() => {
-        delDeviceCalibrationPlan({ planId: id }).then(res => {
-          this.$message.success('鍒犻櫎鎴愬姛锛�');
-          this.getYearTableData();
-        });
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: '宸插彇娑堝垹闄�'
-        });
-      });
-    },
-    // 骞村害璁″垝璇︽儏琛�-鍒犻櫎
-    deleteFun1(id) {
-      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
-        confirmButtonText: '纭畾',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning'
-      }).then(() => {
-        delDeviceCalibrationPlanDetail({ planDetailsId: id }).then(res => {
-          this.$message.success('鍒犻櫎鎴愬姛锛�');
-          this.getYearTableDetailData(this.currentRow)
-        });
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: '宸插彇娑堝垹闄�'
-        });
-      });
-    },
-    currentChange(row) {
-      this.currentRow = row
-      this.getYearTableDetailData(this.currentRow)
-    },
-    getYearTableDetailData(row) {
-      this.yearTableDetailDataLoading = true
-      pageDeviceCalibrationPlanDetail({
-        current: this.pagination1.current,
-        size: this.pagination1.size,
-        planId: row.planId,
-        deviceName: this.searchForm.deviceName,
-        deviceNumber: this.searchForm.deviceNumber,
-      }).then(res => {
-        if (res.code == 200) {
-          this.yearTableDetailData = res.data.records
-          this.pagination1.total = res.data.total
-        }
-        this.yearTableDetailDataLoading = false
-      }).catch(err => {
-        this.yearTableDetailDataLoading = false
-      })
-    },
-    reset() {
-      this.searchForm = {
-        deviceName: '',
-        deviceNumber: '',
-      }
-      this.getYearTableDetailData(this.currentRow)
-    },
-    // 鍒嗛〉
-    handleSizeChange1(val) {
-      this.pagination1.size = val
-      this.getYearTableDetailData(this.currentRow)
-    },
-    // 鍒嗛〉
-    handleCurrentChange1(val) {
-      this.pagination1.current = val
-      this.getYearTableDetailData(this.currentRow)
-    },
-    // 鎵撳紑寮规
-    handleForm(type, row) {
-      this.operationType = type
-      this.dialogVisible = true
-      this.form.planId = this.currentRow.planId
-      if (this.operationType !== 'add') {
-        this.$nextTick(() => {
-          this.form = this.HaveJson(row)
-        })
-      } else {
-        this.form = {
-          deviceName: '',
-          deviceAmount: '',
-          deviceNumber: '',
-          verificationUnit: '',
-          verificationCycles: '',
-          lastDate: '',
-          planDate: '',
-          remark: '',
-          planId: this.currentRow.planId,
-          planDetailId: '',
-        }
-      }
-    },
-    // 鎻愪氦琛ㄥ崟
-    submitForm() {
-      this.$refs.modelForm.validate(valid => {
-        if (valid) {
-          if (this.operationType === 'add') {
-            this.submitFormLoading = true
-            addDeviceCalibrationPlanDetail(this.form).then(res => {
-              if (res.code == 200) {
-                this.$message.success('鏂板鎴愬姛')
-                this.dialogVisible = false
-                this.getYearTableData()
-              }
-              this.submitFormLoading = false
-            }).catch(err => {
-              this.submitFormLoading = false
-            })
-          } else {
-            this.submitFormLoading = true
-            updateDeviceCalibrationPlanDetail(this.form).then(res => {
-              if (res.code == 200) {
-                this.$message.success('鏂板鎴愬姛')
-                this.dialogVisible = false
-                this.getYearTableData()
-              }
-              this.submitFormLoading = false
-            }).catch(err => {
-              this.submitFormLoading = false
-            })
-          }
-        }
-      })
-    },
-    // 鎵撳紑鏂板寮规
-    addYearPlan(type, row) {
-      this.addYearPlanDia = true
-      this.$nextTick(() => {
-        this.$refs.addYearPlanDia.openDialog(type, row)
-      })
-    },
-    closeDia() {
-      this.addYearPlanDia = false
-      this.getYearTableData()
-    },
-    submitUpload() {
-      if (!this.planYear) {
-        this.$message.warning('璇烽�夋嫨骞翠唤')
-        return;
-      }
-      if (this.$refs.upload1.uploadFiles.length === 0) {
-        this.$message.error('鏈�夋嫨鏂囦欢')
-        return
-      }
-      this.uploading = true
-      this.$refs.upload1.submit();
-    },
-    // 鎻愪氦鎵瑰噯
+    // 鎻愪氦鎵瑰噯缁撴灉
     handleApproval(status) {
       const personTrainingUpdateDto = {
         planId: this.currentRowId,
@@ -542,43 +430,22 @@
         if (res.code === 200) {
           this.$message.success('鎻愪氦鎴愬姛锛�');
           this.approvalDialog = false
-          this.getYearTableData();
+          this.loadPlan()
         }
         this.approvalLoading = false
       }).catch(() => {
         this.approvalLoading = false
       })
     },
+    // 瀵煎嚭
+    downLoadPost() {
+      exportDeviceCalibrationPlanDetail({ planId: this.planInfo.planId }).then(res => {
+        saveBlobOrShowError(res, '璁惧鏍″噯璁″垝.docx', 'application/msword')
+      }).catch(() => { })
+    },
     resetForm() {
       this.$refs.modelForm.resetFields();
       this.dialogVisible = false
-    },
-    // 鎵撳紑鎶ュ憡寮规
-    record(row) {
-      this.uploadDia = true
-    },
-    // 瀵煎叆娴佺▼
-    beforeUpload(file) {
-      if (file.size > 1024 * 1024 * 10) {
-        this.$message.error('涓婁紶鏂囦欢涓嶈秴杩�10M');
-        this.$refs.upload.clearFiles()
-        return false;
-      } else {
-        return true;
-      }
-    },
-    onError(err, file, fileList) {
-      this.$message.error('涓婁紶澶辫触')
-      this.$refs.upload.clearFiles()
-    },
-    handleSuccessUp(response) {
-      this.uploading = false;
-      if (response.code == 200) {
-        this.$message.success('涓婁紶鎴愬姛');
-        this.getYearTableData()
-      } else {
-        this.$message.error('涓婁紶澶辫触')
-      }
     },
     // 鑾峰彇璐熻矗浜轰俊鎭帴鍙�
     getUserList() {
@@ -596,12 +463,12 @@
       });
     }
   },
-  // 鐢ㄤ簬涓婁紶鏂囦欢鐨勪俊鎭�
   computed: {
-    action() {
-      return this.javaApi + '/deviceCalibrationPlan/importDeviceCalibrationPlan' + '?planYear=' + this.planYear
-    },
     ...mapGetters(["userId"]),
+    // 鏄惁宸插畬鎴愬鎵癸紙鎵瑰噯/涓嶆壒鍑嗭級
+    isRatified() {
+      return this.planInfo.ratifyStatus === 0 || this.planInfo.ratifyStatus === 1;
+    },
   },
 }
 </script>
@@ -626,9 +493,39 @@
   background-color: var(--el-color-primary);
   border-radius: 2px;
 }
+
+.plan-top {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  flex-wrap: wrap;
+}
+
+.plan-top-left {
+  display: flex;
+  align-items: center;
+}
+
+.plan-info-bar {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: 32px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  padding: 10px 16px;
+  margin-top: 14px;
+  font-size: 14px;
+  color: #606266;
+}
+
 .search {
-  height: 46px;
   display: flex;
   justify-content: space-between;
+  margin-bottom: 10px;
+}
+
+:deep(.red-row td) {
+  background: #ffcccc !important;
 }
 </style>
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentCheck.vue b/src/views/CNAS/resourceDemand/device/component/equipmentCheck.vue
index 5be3be7..e414157 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentCheck.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentCheck.vue
@@ -17,7 +17,7 @@
           <span style="width: 80px">A浠櫒鍚嶇О锛�</span>
           <el-select v-model="form.adeviceId" :disabled="currentStep !== 0" class="table_input" clearable filterable
             placeholder="璁惧鍚嶇О" size="small" style="width:200px" @change="(val) => changeMachineName(val, 'A')">
-            <el-option v-for="item in equipOptions" :key="item.value" :label="item.label" :value="item.id">
+            <el-option v-for="item in equipOptions" :key="item.id" :label="item.label" :value="item.id">
               {{ item.label + '-' + item.value }}
             </el-option>
           </el-select>
@@ -36,7 +36,7 @@
           <span style="width: 80px">B浠櫒鍚嶇О锛�</span>
           <el-select v-model="form.bdeviceId" :disabled="currentStep !== 0" class="table_input" clearable filterable
             placeholder="璁惧鍚嶇О" size="small" style="width:200px" @change="(val) => changeMachineName(val, 'B')">
-            <el-option v-for="item in equipOptions" :key="item.value" :label="item.label" :value="item.id">
+            <el-option v-for="item in equipOptions" :key="item.id" :label="item.label" :value="item.id">
               {{ item.label + '-' + item.value }}
             </el-option>
           </el-select>
@@ -55,7 +55,7 @@
           <span style="width: 80px">C浠櫒鍚嶇О锛�</span>
           <el-select v-model="form.cdeviceId" :disabled="currentStep !== 0" class="table_input" clearable filterable
             placeholder="璁惧鍚嶇О" size="small" style="width:200px" @change="(val) => changeMachineName(val, 'C')">
-            <el-option v-for="item in equipOptions" :key="item.value" :label="item.label" :value="item.id">
+            <el-option v-for="item in equipOptions" :key="item.id" :label="item.label" :value="item.id">
               {{ item.label + '-' + item.value }}
             </el-option>
           </el-select>
@@ -73,7 +73,7 @@
         <el-button v-if="currentStep === 0" size="small" type="primary" @click="addTableRow">娣诲姞</el-button>
       </div>
       <div style="margin: 10px 0">
-        <el-table ref="yearTable" :data="recordContrastDetailsList" height="300px" style="width: 100% ;"
+        <el-table ref="yearTable" :data="form.recordContrastDetailsList" height="300px" style="width: 100% ;"
  border>
           <el-table-column align="center" header-align="center" label="搴忓彿" type="index" width="60"></el-table-column>
           <el-table-column label="鏍告煡椤圭洰" min-width="170" prop="checkItems">
@@ -127,7 +127,7 @@
         </div>
       </div>
       <template #footer><span  class="dialog-footer">
-        <el-button @click="resetForm">鍙� 娑�</el-button>
+        <el-button @click="handleCancel">鍙� 娑�</el-button>
         <el-button v-if="currentStep === 0 && userId == checkChargerUserId" :loading="submitFormLoading" type="primary" @click="submitCheck">纭�
           瀹�</el-button>
         <el-button v-if="currentStep === 1 && userId == reviewUserId" :loading="submitFormLoading" @click="examine(0)">涓嶉�氳繃</el-button>
@@ -179,7 +179,6 @@
         planDetailsId: '',
       },
       equipOptions: [],
-      recordContrastDetailsList: [],
       userList: [],
       checkChargerUserId: '',
       reviewUserId: ''
@@ -202,10 +201,12 @@
       this.searchInfo()
     },
     searchInfo() {
-      getExamineRecordContrast({ planDetailsId: this.form.planDetailsId }).then(res => {
+      const planDetailsId = this.form.planDetailsId
+      getExamineRecordContrast({ planDetailsId }).then(res => {
         if (res.code === 200) {
-          this.form = { ...res.data }
-          this.recordContrastDetailsList = this.form.recordContrastDetailsList || []
+          // 鏃犲巻鍙茶褰曟椂鎺ュ彛鍙兘杩斿洖绌猴紝planDetailsId 蹇呴』淇濈暀锛屽惁鍒欐棤娉曟彁浜�
+          this.form = { ...(res.data || {}), planDetailsId }
+          this.form.recordContrastDetailsList = this.form.recordContrastDetailsList || []
           if (!this.form.reviewUserId) {
             this.currentStep = 0
           } else {
@@ -217,7 +218,6 @@
           this.reviewUserId = this.form.reviewUserId
           if (this.currentStep === 0) {
             this.draftRestore('equipmentCheck', 'form', this.form.planDetailsId, 'dialogVisible')
-            this.recordContrastDetailsList = this.form.recordContrastDetailsList || []
           }
         }
       }).catch(error => {
@@ -226,25 +226,31 @@
     },
     // 璧嬪�间华鍣ㄧ紪鍙�
     changeMachineName(value, type) {
-      const index = this.equipOptions.findIndex(item => item.id === value)
-      if (index > -1) {
-        if (type === 'A') {
-          this.form['adeviceNumber'] = this.equipOptions[index].value
-        }
-        if (type === 'B') {
-          this.form['bdeviceNumber'] = this.equipOptions[index].value
-        }
-        if (type === 'C') {
-          this.form['cdeviceNumber'] = this.equipOptions[index].value
-        }
+      const item = this.equipOptions.find(device => device.id === value)
+      if (type === 'A') {
+        this.form['adeviceNumber'] = item ? item.value : ''
+      }
+      if (type === 'B') {
+        this.form['bdeviceNumber'] = item ? item.value : ''
+      }
+      if (type === 'C') {
+        this.form['cdeviceNumber'] = item ? item.value : ''
       }
     },
     // 娣诲姞琛ㄦ牸鏁版嵁
     addTableRow() {
-      this.recordContrastDetailsList.push({ checkItems: '' })
+      if (!this.form.recordContrastDetailsList) {
+        this.form.recordContrastDetailsList = []
+      }
+      this.form.recordContrastDetailsList.push({ checkItems: '' })
     },
     submitCheck() {
-      this.form.recordContrastDetailsList = this.HaveJson(this.recordContrastDetailsList)
+      const deviceIds = [this.form.adeviceId, this.form.bdeviceId, this.form.cdeviceId].filter(Boolean)
+      if (new Set(deviceIds).size !== deviceIds.length) {
+        this.$message.error('A/B/C 浠櫒涓嶈兘閫夋嫨鍚屼竴鍙拌澶�')
+        return
+      }
+      this.form.recordContrastDetailsList = this.HaveJson(this.form.recordContrastDetailsList || [])
       this.submitFormLoading = true
       addExamineRecordContrast(this.form).then(res => {
         if (res.code == 200) {
@@ -273,6 +279,21 @@
         this.submitFormLoading = false
       })
     },
+    // 鍙栨秷鎸夐挳锛氱‘璁ゅ悗鏁翠綋娓呯┖鏈鑽夌锛涘彸涓婅鍏抽棴/鎰忓閫�鍑哄垯淇濈暀鑽夌
+    handleCancel() {
+      if (this.currentStep !== 0) {
+        this.resetForm()
+        return
+      }
+      this.$confirm('鍙栨秷鍚庢湰娆″~鍐欑殑鏁版嵁灏嗚娓呯┖锛屼笖鏃犳硶鎭㈠锛屾槸鍚︾户缁紵', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '缁х画濉啓',
+        type: 'warning'
+      }).then(() => {
+        this.draftClear('equipmentCheck')
+        this.resetForm()
+      }).catch(() => {})
+    },
     resetForm() {
       this.draftStop('equipmentCheck')
       this.dialogVisible = false
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentFailure.vue b/src/views/CNAS/resourceDemand/device/component/equipmentFailure.vue
index 0f6395d..0bb3be4 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentFailure.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentFailure.vue
@@ -19,15 +19,15 @@
           <!-- 鎿嶄綔鎸夐挳 -->
           <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="140">
             <template #default="scope">
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="primary"
+              <el-button :disabled="scope.row.isFinish === 1" size="small" link type="primary"
                 @click="handleForm(scope.row.maintenanceId)">鎿嶄綔</el-button>
               <el-button size="small" link type="primary" @click="handleDownOne(scope.row.maintenanceId)">瀵煎嚭</el-button>
-              <el-button size="small" link type="danger"
+              <el-button :disabled="scope.row.isFinish === 1" size="small" link type="danger"
                 @click="deleteFun(scope.row.maintenanceId)">鍒犻櫎</el-button>
             </template>
           </el-table-column>
         </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
+        <el-pagination :current-page="pagination1.current" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
           :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper" background
           @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
         </el-pagination>
@@ -44,6 +44,7 @@
   exportDeviceBreakdownMaintenance,
   delDeviceBreakdownMaintenance,
 } from '@/api/cnas/resourceDemand/device.js'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   name: "equipment-failure",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -117,8 +118,9 @@
         maintenanceId: id
       }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '浠櫒璁惧淇悊鐢宠琛�.doc')
+        saveBlobOrShowError(res, '浠櫒璁惧淇悊鐢宠琛�.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     // 鍒犻櫎
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue b/src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue
index 75c1e31..0c661a4 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue
@@ -25,10 +25,13 @@
         <el-row>
           <el-col :span="24">
             <el-form-item label="缁存姢鍐呭:" prop="maintenanceContentArr">
-              <el-checkbox-group v-model="form.maintenanceContentArr" :disabled="operationType === 'view'">
+              <el-checkbox-group v-if="qualificationList.length" v-model="form.maintenanceContentArr"
+                                 :disabled="operationType === 'view'">
                 <el-checkbox v-for="city in qualificationList" :key="city.label" :label="city.label"
                              :value="city.label"></el-checkbox>
               </el-checkbox-group>
+              <el-input v-else v-model="form.maintenanceContentText" :disabled="operationType === 'view'"
+                        size="small" placeholder="璇疯緭鍏ョ淮鎶ゅ唴瀹�" style="width: 100%"></el-input>
             </el-form-item>
           </el-col>
         </el-row>
@@ -67,6 +70,7 @@
 } from "@/api/cnas/resourceDemand/device";
 import limsTable from "@/components/Table/lims-table.vue";
 import {selectUserCondition} from "@/api/system/user";
+import {saveBlobOrShowError} from '@/utils/saveBlob'
 
 export default {
   name: '',
@@ -127,6 +131,7 @@
         maintenanceDate: '',
         maintenanceContentArr: [],
         maintenanceContent: '',
+        maintenanceContentText: '',
         maintenanceUserId: '',
         remark: '',
       },
@@ -135,7 +140,19 @@
       qualificationList: [],
       rules: {
         maintenanceDate: [{ required: true, message: '璇烽�夋嫨缁存姢鏃ユ湡', trigger: 'change' }],
-        maintenanceContentArr: [{ required: true, message: '璇烽�夋嫨缁存姢鍐呭', trigger: 'change' }],
+        maintenanceContentArr: [{
+          validator: (rule, value, callback) => {
+            if (this.qualificationList.length) {
+              if (!value || value.length === 0) {
+                return callback(new Error('璇烽�夋嫨缁存姢鍐呭'))
+              }
+            } else if (!this.form.maintenanceContentText || !this.form.maintenanceContentText.trim()) {
+              return callback(new Error('璇疯緭鍏ョ淮鎶ゅ唴瀹�'))
+            }
+            callback()
+          },
+          trigger: 'change'
+        }],
         maintenanceUserId: [{ required: true, message: '璇烽�夋嫨缁存姢浜�', trigger: 'change' }],
       },
       responsibleOptions: [],
@@ -153,6 +170,7 @@
     },
     // 鍒嗛〉鍒囨崲
     pagination(page) {
+      this.page.current = page.page
       this.page.size = page.limit
       this.getTableList()
     },
@@ -178,7 +196,8 @@
         this.form.id = ''
         if (this.operationType === 'edit') {
           this.form = {...row}
-          this.form['maintenanceContentArr'] = this.form.maintenanceContent.split(',')
+          this.form['maintenanceContentArr'] = this.form.maintenanceContent ? this.form.maintenanceContent.split(',') : []
+          this.form['maintenanceContentText'] = this.form.maintenanceContent || ''
         }
       })
       this.getDictS()
@@ -224,13 +243,14 @@
         deviceId: this.clickNodeVal.value
       }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '璁惧缁存姢淇濆吇.doc')
+        saveBlobOrShowError(res, '璁惧缁存姢淇濆吇.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
 
     },
     handleDeleteClick(row) {
-      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ潯淇濆吇璁板綍, 鏄惁缁х画?', '鎻愮ず', {
         confirmButtonText: '纭畾',
         cancelButtonText: '鍙栨秷',
         type: 'warning'
@@ -254,7 +274,9 @@
       this.$refs.form.validate((valid) => {
         if (valid) {
           this.buttonLoading = true;
-          this.form.maintenanceContent = this.form.maintenanceContentArr.join(',')
+          this.form.maintenanceContent = this.qualificationList.length
+            ? this.form.maintenanceContentArr.join(',')
+            : (this.form.maintenanceContentText || '').trim()
           this.form.deviceId = this.clickNodeVal.value
           addDeviceMaintenance(this.form).then(res => {
             this.buttonLoading = false;
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue b/src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue
index 8605832..7ebc381 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue
@@ -1,150 +1,156 @@
 <template>
+  <!--  璁惧淇濆吇璁″垝-->
   <div>
-    <div>
-      <div style="margin: 10px 0;text-align: right">
-        <el-button size="small" type="primary" @click="getYearTableDetailData">鍒锋柊</el-button>
-        <el-button size="small" type="primary" @click="handleForm('add')">鏂板</el-button>
+    <div style="margin: 10px 0 14px;">
+      <div class="plan-top">
+        <div class="plan-top-left">
+          <span class="title" style="margin-bottom: 0;">{{ planInfo.planName || (planYear + '骞村害璁惧淇濆吇璁″垝') }}</span>
+          <el-select v-model="planYear" size="small" style="width: 110px; margin-left: 16px;" @change="handleYearChange">
+            <el-option v-for="y in yearOptions" :key="y" :label="y" :value="y"></el-option>
+          </el-select>
+        </div>
+        <div>
+          <el-button size="small" type="primary" @click="loadPlan">鍒锋柊</el-button>
+          <el-button size="small" type="primary" :disabled="planInfo.status === 1"
+            @click="tellApprove">瀹℃牳閫氱煡</el-button>
+          <el-button size="small" type="primary"
+            :disabled="planInfo.status === 1 || userId != planInfo.auditId" @click="handleApprove">瀹℃牳</el-button>
+          <el-button size="small" type="primary" :loading="outLoading" @click="handleDownOne">瀵煎嚭</el-button>
+        </div>
       </div>
-      <div>
-        <el-table ref="yearTable" v-loading="yearTableDetailDataLoading" :data="yearTableDetailData"
- border
-          height="calc(100vh - 18em)" style="width: 100% ;">
-          <!-- 琛ㄦ牸鍒� -->
-          <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
-            width="70"></el-table-column>
-          <el-table-column label="骞翠唤" min-width="80" prop="planYear"></el-table-column>
-          <el-table-column label="缂栧埗浜�" min-width="120" prop="compiler"></el-table-column>
-          <el-table-column label="缂栧埗鏃堕棿" min-width="160" prop="datePreparation"></el-table-column>
-          <el-table-column label="瀹℃牳浜�" min-width="150" prop="audit"></el-table-column>
-          <el-table-column label="瀹℃牳鏃堕棿" min-width="180" prop="auditDate"></el-table-column>
-          <el-table-column label="瀹℃牳鐘舵��" min-width="180" prop="status">
-            <template #default="scope">
-              <el-tag v-if="scope.row.status === 1" type="success">閫� 杩�</el-tag>
-              <el-tag v-if="scope.row.status === 0" type="danger">涓嶉�氳繃</el-tag>
-            </template>
-          </el-table-column>
-          <!-- 鎿嶄綔鎸夐挳 -->
-          <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="260">
-            <template #default="scope">
-              <el-button :disabled="scope.row.status === 1" size="small" link type="primary"
-                @click="handleForm('edit', scope.row)">缂栬緫</el-button>
-              <el-button size="small" link type="primary" @click="handleForm('view', scope.row)">鏌ョ湅</el-button>
-              <el-button :disabled="scope.row.status === 1" size="small" link type="primary"
-                @click="tellApprove(scope.row.maintenancePlanId)">瀹℃牳閫氱煡</el-button>
-              <el-button :disabled="scope.row.status === 1 || userId != scope.row.auditId" size="small" link type="primary"
-                @click="handleForm('check', scope.row)">瀹℃牳</el-button>
-              <el-button size="small" link type="primary" @click="handleDownOne(scope.row.maintenancePlanId)">瀵煎嚭</el-button>
-              <el-button :disabled="scope.row.status === 1" size="small" link type="danger"
-                @click="deleteFun(scope.row.maintenancePlanId)">鍒犻櫎</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
-          :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper" background
-          @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
-        </el-pagination>
+      <div class="plan-info-bar">
+        <span>缂栧埗浜猴細{{ planInfo.compiler || '鈥�' }}</span>
+        <span>缂栧埗鏃ユ湡锛歿{ planInfo.datePreparationStr || '鈥�' }}</span>
+        <span v-if="planInfo.status === 1">瀹℃牳鐘舵�侊細<el-tag type="success">閫� 杩�</el-tag></span>
+        <span v-else-if="planInfo.status === 0">瀹℃牳鐘舵�侊細<el-tag type="danger">涓嶉�氳繃</el-tag></span>
+        <span v-else>瀹℃牳鐘舵�侊細<el-tag type="info">鏈鏍�</el-tag></span>
+        <span v-if="planInfo.auditRemark">瀹℃牳淇℃伅锛歿{ planInfo.auditRemark }}</span>
+        <span v-if="isAudited && planInfo.audit">瀹℃牳浜猴細{{ planInfo.audit }}</span>
+        <span v-if="isAudited && planInfo.auditDateStr">瀹℃牳鏃堕棿锛歿{ planInfo.auditDateStr }}</span>
       </div>
     </div>
-    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="applicationForm"
-      title="璁惧淇濆吇璁″垝琛�" width="80%" @close="closeDialog">
-      <div style="display: flex;align-items: center;">
-        <el-button v-if="operationType === 'edit' || operationType === 'add'" size="small" type="primary" @click="addTableRow">娣诲姞</el-button>
-        <span style="width: 60px;margin-left: 10px">骞翠唤锛�</span>
-        <el-date-picker v-model="form.planYear" type="year" value-format="YYYY" clearable size="small" format="YYYY"
-          placeholder="閫夋嫨骞�" :disabled="operationType !== 'edit' && operationType !== 'add'">
-        </el-date-picker>
+    <div class="search">
+      <div>
+        <el-form :model="searchForm" ref="searchForm" size="small" :inline="true">
+          <el-form-item label="璁惧鍚嶇О" prop="deviceName">
+            <el-input v-model="searchForm.deviceName" clearable @keyup.enter="handleQuery"
+              size="small"></el-input>
+          </el-form-item>
+          <el-form-item label="璁惧缂栧彿" prop="deviceNumber">
+            <el-input v-model="searchForm.deviceNumber" @keyup.enter="handleQuery" clearable
+              size="small"></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" size="small" @click="handleQuery">鏌ヨ</el-button>
+            <el-button size="small" @click="reset">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
       </div>
-      <div style="margin: 10px 0">
-        <el-table ref="yearTable" :data="deviceMaintenancePlanDetails" id="templateParamTable" row-key="deviceId"
- border
-          height="560px" style="width: 100% ;">
-          <el-table-column align="center" header-align="center" label="搴忓彿" type="index" width="60"></el-table-column>
-          <el-table-column label="璁惧鍚嶇О" min-width="170" prop="deviceName">
-            <template #default="scope">
-              <el-input v-model="scope.row.deviceName" :disabled="operationType !== 'edit' && operationType !== 'add'" clearable
+    </div>
+    <div>
+      <el-table ref="yearTable" v-loading="tableLoading" :data="tableData" border
+        :row-class-name="tableRowClassName" :height="'calc(100vh - 29em)'" style="width: 100%;">
+        <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
+          width="70"></el-table-column>
+        <el-table-column label="璁惧鍚嶇О鍙婂瀷鍙�" min-width="180" show-overflow-tooltip>
+          <template #default="scope">
+            {{ scope.row.deviceName }}{{ scope.row.specificationModel ? ' ' + scope.row.specificationModel : '' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="璁惧缂栧彿" min-width="140" prop="deviceNumber"></el-table-column>
+        <el-table-column label="褰掑睘瀹為獙瀹�" min-width="120" prop="storagePoint"></el-table-column>
+        <el-table-column label="淇濆吇鍏抽敭閮ㄤ綅" min-width="150" prop="maintenanceSite" show-overflow-tooltip></el-table-column>
+        <el-table-column label="淇濆吇鍐呭" min-width="180" prop="maintenanceContent" show-overflow-tooltip></el-table-column>
+        <el-table-column label="淇濆吇鍛ㄦ湡" min-width="100" prop="maintenanceIntervals"></el-table-column>
+        <el-table-column label="璁″垝淇濆吇鏃堕棿" min-width="130" prop="maintenanceDate"
+          :formatter="formatDateCell"></el-table-column>
+        <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="160">
+          <template #default="scope">
+            <el-button size="small" link type="primary" :disabled="planInfo.status === 1"
+              @click="handleForm('edit', scope.row)">缂栬緫</el-button>
+            <el-button size="small" link type="primary" @click="handleForm('view', scope.row)">鏌ョ湅</el-button>
+            <el-button size="small" link type="danger" :disabled="planInfo.status === 1"
+              @click="deleteRow(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination :current-page="pagination1.current" :page-size="pagination1.size"
+        :page-sizes="[10, 20, 30, 50, 100]" background :total="pagination1.total"
+        layout="->,total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange1"
+        @current-change="handleCurrentChange1">
+      </el-pagination>
+    </div>
+    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible"
+      title="璁惧淇濆吇璁″垝鏄庣粏" width="60%" @close="resetForm">
+      <el-form ref="modelForm" :model="form" :rules="rules" label-width="130px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="璁惧鍚嶇О锛�">
+              <el-input v-model="form.deviceName" disabled size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="璁惧缂栧彿锛�">
+              <el-input v-model="form.deviceNumber" disabled size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="褰掑睘瀹為獙瀹わ細">
+              <el-input v-model="form.storagePoint" disabled size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="淇濆吇鍛ㄦ湡锛�">
+              <el-input v-model="form.maintenanceIntervals" :disabled="operationType === 'view'" clearable
                 size="small"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="璁惧缂栧彿" min-width="140" prop="deviceNumber">
-            <template #default="scope">
-              <el-input v-model="scope.row.deviceNumber" :disabled="operationType !== 'edit' && operationType !== 'add'" clearable
-                size="small"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="褰掑睘瀹為獙瀹�" min-width="120" prop="storagePoint">
-            <template #default="scope">
-              <el-input v-model="scope.row.storagePoint" :disabled="operationType !== 'edit' && operationType !== 'add'" clearable
-                size="small"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="淇濆吇鍏抽敭閮ㄤ綅" min-width="120" prop="maintenanceSite">
-            <template #default="scope">
-              <el-input v-model="scope.row.maintenanceSite" :disabled="operationType !== 'edit' && operationType !== 'add'" clearable size="small"
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="淇濆吇鍏抽敭閮ㄤ綅锛�">
+              <el-input v-model="form.maintenanceSite" :disabled="operationType === 'view'" clearable size="small"
                 type="textarea"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="淇濆吇鍐呭" min-width="120" prop="maintenanceContent">
-            <template #default="scope">
-              <el-input v-model="scope.row.maintenanceContent" :disabled="operationType !== 'edit' && operationType !== 'add'" clearable
-                size="small" type="textarea"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="淇濆吇鍛ㄦ湡" min-width="90" prop="maintenanceIntervals">
-            <template #default="scope">
-              <el-input v-model="scope.row.maintenanceIntervals" :disabled="operationType !== 'edit' && operationType !== 'add'" clearable
-                size="small"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="璁″垝淇濆吇鏃堕棿" min-width="140" prop="maintenanceDate">
-            <template #default="scope">
-              <el-date-picker v-model="scope.row.maintenanceDate" :disabled="operationType !== 'edit' && operationType !== 'add'" clearable
-                size="small" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" style="width:100%"></el-date-picker>
-            </template>
-          </el-table-column>
-          <el-table-column label="鎿嶄綔" width="80" align="center" v-if="operationType === 'edit' || operationType === 'add'">
-            <template #default="scope">
-              <el-button link type="danger" @click="deleteRow(scope.$index)">鍒犻櫎</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-      </div>
-      <template #footer><span  class="dialog-footer">
-        <el-button @click="closeDialog">鍙� 娑�</el-button>
-        <el-button v-if="operationType === 'edit' || operationType === 'add'" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
-          璁�</el-button>
-        <el-button v-if="operationType === 'check'" :loading="submitFormLoading" type="primary"
-          @click="checkStatus(0)">涓嶉�氳繃</el-button>
-        <el-button v-if="operationType === 'check'" :loading="submitFormLoading" type="primary"
-          @click="checkStatus(1)">閫�
-          杩�</el-button>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="淇濆吇鍐呭锛�">
+              <el-input v-model="form.maintenanceContent" :disabled="operationType === 'view'" clearable size="small"
+                type="textarea"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="璁″垝淇濆吇鏃堕棿锛�" prop="maintenanceDate">
+              <el-date-picker v-model="form.maintenanceDate" :disabled="operationType === 'view'" clearable
+                format="YYYY-MM-DD" placeholder="閫夋嫨鏃ユ湡" size="small" style="width:100%" type="date"
+                value-format="YYYY-MM-DD"></el-date-picker>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer><span class="dialog-footer">
+        <el-button @click="resetForm">鍙� 娑�</el-button>
+        <el-button :loading="submitFormLoading" type="primary" @click="submitForm"
+          v-if="operationType !== 'view'">纭� 璁�</el-button>
       </span></template>
     </el-dialog>
-    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="addEquipDia" title="娣诲姞璁惧"
-      width="50%">
-      <el-table ref="multipleTable" :data="equipOptions" tooltip-effect="dark" height="500" style="width: 100%"
- border
-        @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55"></el-table-column>
-        <el-table-column label="璁惧鍚嶇О" prop="label" width="190"></el-table-column>
-        <el-table-column prop="value" label="璁惧缂栧彿" width="130"></el-table-column>
-        <el-table-column prop="managementNumber" label="褰掑睘瀹為獙瀹�"></el-table-column>
-      </el-table>
-      <template #footer><span  class="dialog-footer">
-        <el-button @click="addEquipDia = false">鍙� 娑�</el-button>
-        <el-button v-if="operationType === 'edit' || operationType === 'add'" :loading="submitFormLoading" type="primary"
-          @click="changeMachineName">纭�
-          璁�</el-button>
+    <el-dialog v-model="approvalDialog" title="瀹℃牳" width="30%" @close="approvalDialog = false">
+      <span>
+        瀹℃牳淇℃伅锛�
+        <el-input v-model="approvalRemark" type="textarea"></el-input>
+      </span>
+      <template #footer><span class="dialog-footer">
+        <el-button :loading="approvalLoading" @click="handleApproval(0)">涓嶉�氳繃</el-button>
+        <el-button :loading="approvalLoading" type="primary" @click="handleApproval(1)">閫� 杩�</el-button>
       </span></template>
     </el-dialog>
     <el-dialog v-model="notificationDia" title="鎻愪氦瀹℃牳" width="30%" @close="closeNotificationDia">
       <span style="margin-top: 10px;display: inline-block">
         璇烽�夋嫨瀹℃牳浜猴細
-        <el-select v-model="auditId" clearable filterable size="small" style="width: 90%;">
-          <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id">
+        <el-select v-model="auditUserId" clearable filterable size="small" style="width: 90%;">
+          <el-option v-for="item in responsibleOptions" :key="item.value" :label="item.label" :value="item.value">
           </el-option>
         </el-select>
       </span>
-      <template #footer><span  class="dialog-footer">
+      <template #footer><span class="dialog-footer">
         <el-button :loading="notificationLoading" @click="closeNotificationDia">鍙� 娑�</el-button>
         <el-button :loading="notificationLoading" type="primary" @click="notification">鎻� 浜�</el-button>
       </span></template>
@@ -153,253 +159,213 @@
 </template>
 
 <script>
-import Sortable from "sortablejs";
 import {
   selectDeviceMaintenancePlanByPage,
   submitReviewMaintenancePlanStatus,
-  getMaintenancePlanDetail,
-  addMaintenancePlan,
-  updateMaintenancePlan,
+  getMaintenancePlanByYear,
+  pageMaintenancePlanDetail,
+  updateMaintenancePlanDetail,
+  deleteMaintenancePlanDetail,
   exportDeviceMaintenancePlan,
-  deleteMaintenancePlan,
-  deviceScopeSearch,
+  reviewMaintenancePlanStatus,
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
 import { mapGetters } from "@/utils/store-compat";
+import { formatDateOnly } from './dateFormat'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   name: "equipment-maintenance-plan",
-  // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
-  components: {},
   props: {
     clickNodeVal: {
       type: Object,
       default: () => {
+        return {};
       }
     }
   },
   data() {
-    // 杩欓噷瀛樻斁鏁版嵁
     return {
+      planYear: '',
+      yearOptions: [],
+      planInfo: {},
+      searchForm: {
+        deviceName: '',
+        deviceNumber: '',
+      },
+      tableData: [],
+      tableLoading: false,
       pagination1: {
         size: 10,
         current: 1,
         total: 0,
       },
-      yearTableDetailDataLoading: false,
-      yearTableDetailData: [],
-      deviceMaintenancePlanDetails: [],
-      selectionRows: [],
-      deviceIds: [],
-      applicationForm: false,
-      submitFormLoading: false,
+      dialogVisible: false,
       operationType: '',
-      equipOptions: [],
-      form: {
-        planYear: '',
-        deviceMaintenancePlanDetails: []
+      form: {},
+      rules: {
+        maintenanceDate: [{ required: true, message: '璇烽�夋嫨璁″垝淇濆吇鏃堕棿', trigger: 'change' }],
       },
-      addEquipDia: false,
+      submitFormLoading: false,
+      outLoading: false,
       responsibleOptions: [],
       notificationDia: false,
       notificationLoading: false,
-      auditId: '',
-      maintenancePlanId: ''
+      auditUserId: '',
+      approvalDialog: false,
+      approvalLoading: false,
+      approvalRemark: '',
     }
   },
   mounted() {
-    this.getYearTableDetailData()
+    this.loadYearOptions()
   },
-  // 鏂规硶闆嗗悎
   methods: {
-    // 鏌ヨ
-    getYearTableDetailData() {
-      this.yearTableDetailDataLoading = true
-      selectDeviceMaintenancePlanByPage({
-        current: this.pagination1.current,
-        size: this.pagination1.size,
-      }).then(res => {
-        if (res.code == 200) {
-          this.yearTableDetailData = res.data.records
-          this.pagination1.total = res.data.total
+    // 骞翠唤涓嬫媺閫夐」锛氬凡鏈夎鍒掑勾浠� + 褰撳墠骞翠唤
+    loadYearOptions() {
+      const currentYear = String(new Date().getFullYear())
+      const finish = (years) => {
+        if (years.indexOf(currentYear) === -1) {
+          years.push(currentYear)
         }
-        this.yearTableDetailDataLoading = false
-      }).catch(err => {
-        this.yearTableDetailDataLoading = false
+        this.yearOptions = [...new Set(years)].sort((a, b) => b.localeCompare(a))
+        this.planYear = currentYear
+        this.loadPlan()
+      }
+      selectDeviceMaintenancePlanByPage({
+        current: 1,
+        size: 99,
+      }).then(res => {
+        let years = []
+        if (res.code == 200) {
+          years = (res.data.records || []).map(r => r.planYear).filter(Boolean)
+        }
+        finish(years)
+      }).catch(() => {
+        finish([])
       })
     },
-    // 鎵撳紑鎻愪氦鎵瑰噯寮规
-    tellApprove(maintenancePlanId) {
-      this.getUserList()
-      this.notificationDia = true
-      this.maintenancePlanId = maintenancePlanId
+    // 鍒囨崲骞翠唤
+    handleYearChange() {
+      this.pagination1.current = 1
+      this.loadPlan()
     },
-    // 鍏抽棴鎻愪氦鎵瑰噯寮规
-    closeNotificationDia() {
-      this.notificationDia = false
-      this.auditId = ''
+    // 鏌ヨ骞翠唤璁″垝锛堜笉瀛樺湪鑷姩鍒涘缓骞惰ˉ鍏ㄥ埌鐐规槑缁嗭級锛岄殢鍚庡埛鏂版槑缁�
+    loadPlan() {
+      getMaintenancePlanByYear({ planYear: this.planYear }).then(res => {
+        if (res.code == 200) {
+          this.planInfo = res.data || {}
+        }
+        this.getTableList()
+      }).catch(() => {
+        this.planInfo = {}
+        this.tableData = []
+        this.pagination1.total = 0
+        this.tableLoading = false
+      })
     },
-    // 鎻愪氦鎵瑰噯閫氱煡
-    notification() {
-      if (!this.auditId) {
-        this.$message.warning('璇烽�夋嫨瀹℃牳浜�')
+    // 鏌ヨ鏉′欢鍙樺寲鍚庝粠绗竴椤靛紑濮嬫煡
+    handleQuery() {
+      this.pagination1.current = 1
+      this.getTableList()
+    },
+    // 鏄庣粏-鏌ヨ
+    getTableList() {
+      if (!this.planInfo.maintenancePlanId) {
         return
       }
-      this.notificationLoading = true
-      submitReviewMaintenancePlanStatus({
-        auditId: this.auditId,
-        maintenancePlanId: this.maintenancePlanId,
+      this.tableLoading = true
+      pageMaintenancePlanDetail({
+        current: this.pagination1.current,
+        size: this.pagination1.size,
+        planId: this.planInfo.maintenancePlanId,
+        deviceName: this.searchForm.deviceName,
+        deviceNumber: this.searchForm.deviceNumber,
       }).then(res => {
-        this.notificationLoading = false
         if (res.code == 200) {
-          this.closeNotificationDia()
-          this.getYearTableDetailData()
+          this.tableData = res.data.records
+          this.pagination1.total = res.data.total
         }
-      }).catch(err => {
-        this.notificationLoading = false
+        this.tableLoading = false
+      }).catch(() => {
+        this.tableLoading = false
       })
     },
-    // 鎵撳紑鏂板鍜岀紪杈戝脊妗�
-    handleForm(type, row) {
-      this.operationType = type
-      this.applicationForm = true
-      this.form = {
-        planYear: '',
-        deviceMaintenancePlanDetails: [],
+    // 鍒扮偣闇�淇濆吇鐨勮鏍囩孩
+    formatDateCell(row, column, cellValue) {
+      return formatDateOnly(cellValue)
+    },
+    tableRowClassName({ row }) {
+      return row.redFlag === 1 ? 'red-row' : ''
+    },
+    reset() {
+      this.searchForm = {
+        deviceName: '',
+        deviceNumber: '',
       }
-      this.deviceMaintenancePlanDetails = []
-      if (row) {
-        this.maintenancePlanId = row.maintenancePlanId
-        getMaintenancePlanDetail({ maintenancePlanId: this.maintenancePlanId }).then(res => {
-          if (res.code === 200) {
-            this.form = res.data
-            this.deviceMaintenancePlanDetails = this.form.deviceMaintenancePlanDetails
-          }
-        }).catch(error => {
-          console.error(error)
-        })
-      }
-      this.getEquipOptions()
-    },
-    // 娣诲姞璁惧
-    addTableRow() {
-      this.addEquipDia = true
-      this.getEquipOptions()
-    },
-    handleSelectionChange(selection) {
-      this.selectionRows = selection
-    },
-    // 璧嬪�间华鍣ㄧ紪鍙�
-    changeMachineName() {
-      this.deviceMaintenancePlanDetails = []
-      this.selectionRows.map(val => {
-        this.deviceMaintenancePlanDetails.push({ deviceId: val.id, deviceName: val.label, deviceNumber: val.value, storagePoint: val.storagePoint })
-      })
-      this.addEquipDia = false
-      this.rowDrop()
-    },
-    rowDrop() {
-      const that = this
-      const tbody = document.querySelector(
-        '#templateParamTable .el-table__body-wrapper tbody'
-      )
-      if (!this.sortTable) {
-        this.sortTable = Sortable.create(tbody, {
-          animation: 200, //鍔ㄧ敾鏃堕暱
-          handle: ".el-table__row", //鍙嫋鎷藉尯鍩焎lass
-          //鎷栨嫿涓簨浠�
-          onMove: ({ dragged, related }) => {
-            const oldRow = that.deviceMaintenancePlanDetails[dragged.rowIndex] //鏃т綅缃暟鎹�
-            const newRow = that.deviceMaintenancePlanDetails[related.rowIndex] //琚嫋鎷界殑鏂版暟鎹�
-          },
-          //鎷栨嫿缁撴潫浜嬩欢
-          onEnd: evt => {
-            const curRow = that.deviceMaintenancePlanDetails.splice(evt.oldIndex, 1)[0];
-            that.deviceMaintenancePlanDetails.splice(evt.newIndex, 0, curRow);
-          }
-        })
-      }
-    },
-    // 鍒犻櫎琛ㄦ牸琛�
-    deleteRow(index) {
-      this.deviceMaintenancePlanDetails.splice(index, 1)
-    },
-    // 鎻愪氦鏂板鍜屼慨鏀�
-    submitForm() {
-      this.form.deviceMaintenancePlanDetails = this.HaveJson(this.deviceMaintenancePlanDetails)
-      this.submitFormLoading = true
-      if (this.operationType === 'add') {
-        addMaintenancePlan(this.form).then(res => {
-          if (res.code == 200) {
-            this.$message.success('鏂板鎴愬姛')
-            this.applicationForm = false
-            this.getYearTableDetailData()
-          }
-          this.submitFormLoading = false
-        }).catch(err => {
-          this.submitFormLoading = false
-        })
-      } else {
-        updateMaintenancePlan(this.form).then(res => {
-          if (res.code == 200) {
-            this.$message.success('淇敼鎴愬姛')
-            this.applicationForm = false
-            this.getYearTableDetailData()
-          }
-          this.submitFormLoading = false
-        }).catch(err => {
-          this.submitFormLoading = false
-        })
-      }
-    },
-    // 鎻愪氦瀹℃牳
-    checkStatus(status) {
-      const params = {
-        status: status,
-        maintenancePlanId: this.maintenancePlanId
-      }
-      addMaintenancePlan(params).then(res => {
-        if (res.code == 200) {
-          this.$message.success('瀹℃牳鎴愬姛')
-          this.applicationForm = false
-          this.getYearTableDetailData()
-        }
-        this.submitFormLoading = false
-      }).catch(err => {
-        this.submitFormLoading = false
-      })
-    },
-    closeDialog() {
-      this.applicationForm = false
-      this.getYearTableDetailData()
+      this.pagination1.current = 1
+      this.getTableList()
     },
     // 鍒嗛〉
     handleSizeChange1(val) {
       this.pagination1.size = val
-      this.getYearTableDetailData()
+      this.getTableList()
     },
     // 鍒嗛〉
     handleCurrentChange1(val) {
       this.pagination1.current = val
-      this.getYearTableDetailData()
+      this.getTableList()
     },
-    handleDownOne(id) {
-      this.outLoading = true
-      exportDeviceMaintenancePlan({ maintenancePlanId: id }).then(res => {
-        this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '璁惧缁存姢淇濆吇璁板綍.doc')
+    // 鎵撳紑鏄庣粏寮规
+    handleForm(type, row) {
+      this.operationType = type
+      this.form = this.HaveJson(row)
+      this.dialogVisible = true
+      this.$nextTick(() => {
+        if (this.$refs.modelForm) {
+          this.$refs.modelForm.clearValidate()
+        }
       })
     },
-    // 鍒犻櫎
-    deleteFun(id) {
-      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+    // 鎻愪氦琛ㄥ崟锛堝彧鍥炰紶鏄庣粏琛ㄥ瓧娈碉級
+    submitForm() {
+      this.$refs.modelForm.validate(valid => {
+        if (valid) {
+          this.submitFormLoading = true
+          const payload = {
+            maintenancePlanDetailId: this.form.maintenancePlanDetailId,
+            maintenancePlanId: this.form.maintenancePlanId,
+            deviceId: this.form.deviceId,
+            maintenanceSite: this.form.maintenanceSite,
+            maintenanceContent: this.form.maintenanceContent,
+            maintenanceIntervals: this.form.maintenanceIntervals,
+            maintenanceDate: this.form.maintenanceDate,
+          }
+          updateMaintenancePlanDetail(payload).then(res => {
+            if (res.code == 200) {
+              this.$message.success('淇敼鎴愬姛')
+              this.dialogVisible = false
+              this.getTableList()
+            }
+            this.submitFormLoading = false
+          }).catch(() => {
+            this.submitFormLoading = false
+          })
+        }
+      })
+    },
+    resetForm() {
+      this.dialogVisible = false
+    },
+    // 鏄庣粏-鍒犻櫎
+    deleteRow(row) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ潯鏄庣粏, 鏄惁缁х画?', '鎻愮ず', {
         confirmButtonText: '纭畾',
         cancelButtonText: '鍙栨秷',
         type: 'warning'
       }).then(() => {
-        deleteMaintenancePlan({ maintenancePlanId: id }).then(res => {
+        deleteMaintenancePlanDetail({ maintenancePlanDetailId: row.maintenancePlanDetailId }).then(() => {
           this.$message.success('鍒犻櫎鎴愬姛锛�');
-          this.getYearTableDetailData();
+          this.getTableList()
         });
       }).catch(() => {
         this.$message({
@@ -408,54 +374,144 @@
         });
       });
     },
-    // 鑾峰彇鎵�鏈夎澶�
-    getEquipOptions() {
-      this.equipOptions = []
-      deviceScopeSearch({ status: 0 }).then(res => {
-        if (res.code === 200 && res.data) {
-          this.equipOptions = res.data.map(m => {
-            m.value = m.managementNumber
-            m.label = m.deviceName
-            return m
-          })
+    // 鎵撳紑鎻愪氦瀹℃牳寮规
+    tellApprove() {
+      this.getUserList()
+      this.notificationDia = true
+    },
+    // 鍏抽棴鎻愪氦瀹℃牳寮规
+    closeNotificationDia() {
+      this.notificationDia = false
+      this.auditUserId = ''
+    },
+    // 鎻愪氦瀹℃牳閫氱煡
+    notification() {
+      if (!this.auditUserId) {
+        this.$message.warning('璇烽�夋嫨瀹℃牳浜�')
+        return
+      }
+      this.notificationLoading = true
+      submitReviewMaintenancePlanStatus({
+        auditId: this.auditUserId,
+        maintenancePlanId: this.planInfo.maintenancePlanId,
+      }).then(res => {
+        this.notificationLoading = false
+        if (res.code == 200) {
+          this.closeNotificationDia()
+          this.loadPlan()
         }
-      }).catch(error => {
-        console.error(error)
+      }).catch(() => {
+        this.notificationLoading = false
+      })
+    },
+    // 鎵撳紑瀹℃牳寮规
+    handleApprove() {
+      this.approvalRemark = ''
+      this.approvalDialog = true
+    },
+    // 鎻愪氦瀹℃牳缁撴灉
+    handleApproval(status) {
+      this.approvalLoading = true
+      reviewMaintenancePlanStatus({
+        maintenancePlanId: this.planInfo.maintenancePlanId,
+        status: status,
+        auditRemark: this.approvalRemark,
+      }).then(res => {
+        if (res.code == 200) {
+          this.$message.success('瀹℃牳鎴愬姛锛�');
+          this.approvalDialog = false
+          this.loadPlan()
+        }
+        this.approvalLoading = false
+      }).catch(() => {
+        this.approvalLoading = false
+      })
+    },
+    // 瀵煎嚭
+    handleDownOne() {
+      this.outLoading = true
+      exportDeviceMaintenancePlan({ maintenancePlanId: this.planInfo.maintenancePlanId }).then(res => {
+        this.outLoading = false
+        saveBlobOrShowError(res, '璁惧淇濆吇璁″垝琛�.docx', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     // 鑾峰彇璐熻矗浜轰俊鎭帴鍙�
     getUserList() {
       selectUserCondition().then(res => {
         if (res.code == 200) {
-          this.responsibleOptions = res.data
+          this.responsibleOptions = (res.data || []).map(item => ({
+            label: item.name,
+            value: item.id,
+          }))
         }
       });
     }
   },
-  watch: {
-    // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
-    clickNodeVal(newVal) {
-      if (newVal.value) {
-        this.getYearTableDetailData();
-      }
-    },
-  },
   computed: {
     ...mapGetters(["userId"]),
+    // 鏄惁宸插畬鎴愬鏍革紙閫氳繃/涓嶉�氳繃锛�
+    isAudited() {
+      return this.planInfo.status === 0 || this.planInfo.status === 1;
+    },
   },
 }
 </script>
 
 <style scoped>
 .title {
+  position: relative;
+  font-size: 16px;
+  color: var(--lims-text);
+  font-weight: 400;
+  padding-left: 10px;
+  margin-bottom: 10px;
+}
+
+.title::before {
+  position: absolute;
+  left: 0;
+  top: 4px;
+  content: '';
+  width: 4px;
+  height: 16px;
+  background-color: var(--el-color-primary);
+  border-radius: 2px;
+}
+
+.plan-top {
   display: flex;
+  align-items: center;
   justify-content: space-between;
+  flex-wrap: wrap;
+}
+
+.plan-top-left {
+  display: flex;
   align-items: center;
 }
 
-.title-search {
+.plan-info-bar {
   display: flex;
   align-items: center;
-  margin: 10px 0;
+  flex-wrap: wrap;
+  gap: 32px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  padding: 10px 16px;
+  margin-top: 14px;
+  font-size: 14px;
+  color: #606266;
+}
+
+.search {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+
+:deep(.red-row td) {
+  background: #ffcccc !important;
 }
 </style>
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentScrap.vue b/src/views/CNAS/resourceDemand/device/component/equipmentScrap.vue
index 799517f..6c7f04f 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentScrap.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentScrap.vue
@@ -15,20 +15,22 @@
           <!--          <el-table-column label="浠櫒鍚嶇О" min-width="150" prop="unitName"></el-table-column>-->
           <!--          <el-table-column label="鍨嬪彿" min-width="100" prop="address"></el-table-column>-->
           <el-table-column label="閰嶄欢" min-width="150" prop="parts"></el-table-column>
-          <el-table-column label="缂栧彿" min-width="100" prop="number"></el-table-column>
+          <el-table-column label="缂栧彿" min-width="100">
+            <template v-slot="scope">{{ scope.row.number || clickNodeVal.managementNumber || '-' }}</template>
+          </el-table-column>
           <el-table-column label="鎶ュ簾鐞嗙敱" min-width="150" prop="reasonsForScrap"></el-table-column>
           <!-- 鎿嶄綔鎸夐挳 -->
           <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="120">
             <template #default="scope">
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="primary"
+              <el-button :disabled="scope.row.isFinish === 1" size="small" link type="primary"
                 @click="handleForm(scope.row.scrappedId)">鎿嶄綔</el-button>
               <el-button size="small" link type="primary" @click="handleDownOne(scope.row.scrappedId)">瀵煎嚭</el-button>
-              <el-button size="small" link type="danger"
+              <el-button :disabled="scope.row.isFinish === 1" size="small" link type="danger"
                 @click="deleteFun(scope.row.scrappedId)">鍒犻櫎</el-button>
             </template>
           </el-table-column>
         </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
+        <el-pagination :current-page="pagination1.current" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
           :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper"
           @size-change="handleSizeChange1" @current-change="handleCurrentChange1" background>
         </el-pagination>
@@ -46,6 +48,7 @@
   exportDeviceScrapped,
   delDeviceScrapped,
 } from '@/api/cnas/resourceDemand/device.js'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   name: "equipment-scrap",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -117,8 +120,9 @@
       this.outLoading = true
       exportDeviceScrapped({ scrappedId: id }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '浠櫒璁惧鎶ュ簾鐢宠琛�.doc')
+        saveBlobOrShowError(res, '浠櫒璁惧鎶ュ簾鐢宠琛�.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     // 鍒犻櫎
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue b/src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue
index 0aa34b9..028e5e2 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue
@@ -1,137 +1,101 @@
 <template>
   <!--  璁惧鏍告煡璁″垝-->
   <div>
-    <div>
-      <div style="margin: 10px 0;display: flex;align-items: center;justify-content: space-between;">
-        <div class="title">
-          <span style="font-weight: bold">骞村害璁″垝琛�</span>
+    <div style="margin: 10px 0 14px;">
+      <div class="plan-top">
+        <div class="plan-top-left">
+          <span class="title" style="margin-bottom: 0;">{{ planInfo.planName || (planYear + '骞村害璁惧鏍告煡璁″垝') }}</span>
+          <el-select v-model="planYear" size="small" style="width: 110px; margin-left: 16px;" @change="handleYearChange">
+            <el-option v-for="y in yearOptions" :key="y" :label="y" :value="y"></el-option>
+          </el-select>
         </div>
-        <div style="display: flex;align-items: center;">
-          <el-button size="small" type="primary" @click="getYearTableData">鍒锋柊</el-button>
-          <el-button size="small" type="primary" @click="addYearPlan('add')">鏂板</el-button>
-          <!--          <el-upload ref="upload" :action="action"-->
-          <!--                     :before-upload="beforeUpload" :headers="uploadHeader" :on-error="onError"-->
-          <!--                     :on-success="handleSuccessUp" :show-file-list="false" accept='.xls,.xlsx'>-->
-          <!--            <el-button :loading="upLoading" size="small" type="primary">瀵煎叆</el-button>-->
-          <!--          </el-upload>-->
+        <div>
+          <el-button size="small" type="primary" @click="loadPlan">鍒锋柊</el-button>
+          <el-button size="small" type="primary" :disabled="planInfo.ratifyStatus === 1"
+            @click="tellApprove">鎵瑰噯閫氱煡</el-button>
+          <el-button size="small" type="primary"
+            :disabled="planInfo.ratifyStatus === 1 || userId != planInfo.ratifyUserId" @click="handleApprove">鎵瑰噯</el-button>
+          <el-button size="small" type="primary" @click="downLoadPost">瀵煎嚭</el-button>
         </div>
       </div>
+      <div class="plan-info-bar">
+        <span>缂栧埗浜猴細{{ planInfo.writeName || '鈥�' }}</span>
+        <span>缂栧埗鏃ユ湡锛歿{ planInfo.writeTimeStr || '鈥�' }}</span>
+        <span v-if="planInfo.ratifyStatus === 1">鎵瑰噯鐘舵�侊細<el-tag type="success">鎵瑰噯</el-tag></span>
+        <span v-else-if="planInfo.ratifyStatus === 0">鎵瑰噯鐘舵�侊細<el-tag type="danger">涓嶆壒鍑�</el-tag></span>
+        <span v-if="planInfo.ratifyRemark">鎵瑰噯鍐呭锛歿{ planInfo.ratifyRemark }}</span>
+        <span v-if="isRatified && planInfo.ratifyName">鎵瑰噯浜猴細{{ planInfo.ratifyName }}</span>
+        <span v-if="isRatified && planInfo.ratifyTimeStr">鎵瑰噯鏃堕棿锛歿{ planInfo.ratifyTimeStr }}</span>
+      </div>
+    </div>
+    <div class="search">
       <div>
-        <el-table ref="yearTable" v-loading="yearTableDataLoading" :data="yearTableData"
-                  height="calc(60vh - 16em)"
- border
-                  highlight-current-row @current-change="currentChange">
-          <!-- 琛ㄦ牸鍒� -->
-          <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
-            width="70"></el-table-column>
-          <el-table-column label="骞翠唤" min-width="80" prop="planYear"></el-table-column>
-          <el-table-column label="璁″垝鍚嶇О" min-width="180" prop="planName" show-overflow-tooltip></el-table-column>
-          <el-table-column label="缂栧埗浜�" min-width="100" prop="writeName"></el-table-column>
-          <el-table-column label="缂栧埗鏃ユ湡" min-width="160" prop="writeTime"></el-table-column>
-          <el-table-column label="鎵瑰噯鐘舵��" min-width="100" prop="ratifyStatus">
-            <template #default="scope">
-              <el-tag v-if="scope.row.ratifyStatus === 1" type="success">鎵瑰噯</el-tag>
-              <el-tag v-if="scope.row.ratifyStatus === 0" type="danger">涓嶆壒鍑�</el-tag>
-            </template>
-          </el-table-column>
-          <el-table-column label="鎵瑰噯鍐呭" min-width="150" prop="ratifyRemark"></el-table-column>
-          <el-table-column label="鎵瑰噯浜�" min-width="100" prop="ratifyName"></el-table-column>
-          <el-table-column label="鎵瑰噯鏃堕棿" min-width="150" prop="ratifyTime"></el-table-column>
-          <!-- 鎿嶄綔鎸夐挳 -->
-          <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="240">
-            <template #default="scope">
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="primary"
-                @click="addYearPlan('edit', scope.row)">缂栬緫</el-button>
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="primary"
-                @click="tellApprove(scope.row.planId)">鎵瑰噯閫氱煡</el-button>
-              <el-button :disabled="scope.row.ratifyStatus === 1 || userId != scope.row.ratifyUserId" size="small"
-                link type="primary" @click="handleApprove(scope.row.planId)">鎵瑰噯</el-button>
-              <el-button size="small" link type="primary" @click="downLoadPost(scope.row.planId)">瀵煎嚭</el-button>
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="danger"
-                @click="deleteFun(scope.row.planId)">鍒犻櫎</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-        <el-pagination :current-page="1" :page-size="pagination.size" :page-sizes="[10, 20, 30, 50, 100]"
-                       background :total="pagination.total" layout="->,total, sizes, prev, pager, next, jumper"
-                       @size-change="handleSizeChange" @current-change="handleCurrentChange">
-        </el-pagination>
+        <el-form :model="searchForm" ref="searchForm" size="small" :inline="true">
+          <el-form-item label="璁惧缂栧彿" prop="deviceNumber">
+            <el-input v-model="searchForm.deviceNumber" clearable size="small"
+              @keyup.enter="handleQuery"></el-input>
+          </el-form-item>
+          <el-form-item label="璁惧鍚嶇О" prop="deviceName">
+            <el-input v-model="searchForm.deviceName" clearable size="small"
+              @keyup.enter="handleQuery"></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" size="small" @click="handleQuery">鏌ヨ</el-button>
+            <el-button size="small" @click="reset">閲嶇疆</el-button>
+          </el-form-item>
+        </el-form>
       </div>
     </div>
     <div>
-      <div class="title">
-        <span style="font-weight: bold">骞村害璁″垝鏄庣粏琛�</span>
-      </div>
-      <div class="search">
-        <div>
-          <el-form :model="searchForm" ref="searchForm" size="small" :inline="true">
-            <el-form-item label="璁惧缂栧彿" prop="deviceNumber">
-              <el-input v-model="searchForm.deviceNumber" clearable size="small"
-                        @keyup.enter="getYearTableDetailData(currentRow)"></el-input>
-            </el-form-item>
-            <el-form-item label="璁惧鍚嶇О" prop="deviceName">
-              <el-input v-model="searchForm.deviceName" clearable size="small"
-                        @keyup.enter="getYearTableDetailData(currentRow)"></el-input>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" size="small" @click="getYearTableDetailData(currentRow)">鏌ヨ</el-button>
-              <el-button size="small" @click="reset">閲嶇疆</el-button>
-            </el-form-item>
-          </el-form>
-        </div>
-        <div>
-          <el-button size="small" type="primary" @click="handleForm('add')">鏂板</el-button>
-        </div>
-      </div>
-      <div>
-        <el-table ref="yearTableDetailData" v-loading="yearTableDetailDataLoading" :data="yearTableDetailData"
- border
-                  :height="'calc(100vh - 34em)'" style="width: 100% ;">
-          <!-- 琛ㄦ牸鍒� -->
-          <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
-            width="70"></el-table-column>
-          <el-table-column label="璁惧缂栧彿" min-width="180" prop="deviceNumber"></el-table-column>
-          <el-table-column label="璁惧鍚嶇О" min-width="180" prop="deviceName" show-overflow-tooltip></el-table-column>
-          <el-table-column label="鏍告煡鏃堕棿" min-width="150" prop="checkTime"></el-table-column>
-          <el-table-column label="鏍告煡鎸囨爣" min-width="150" prop="checkIndex"> </el-table-column>
-          <el-table-column label="鏍告煡鏂规硶" min-width="150" prop="checkMethod"></el-table-column>
-          <el-table-column label="缁撴灉濡備綍鍒ゅ畾" min-width="150" prop="howResults"></el-table-column>
-          <el-table-column label="鏍告煡璐熻矗浜�" min-width="150" prop="checkChargerUser"></el-table-column>
-          <el-table-column label="璁板綍鐘舵��" min-width="100" prop="recordStatus">
-            <template #default="scope">
-              <el-tag type="" v-if="scope.row.recordStatus === 0" disable-transitions>鏈紑濮�</el-tag>
-              <el-tag type="warning" v-if="scope.row.recordStatus === 1" disable-transitions>寰呮壒鍑�</el-tag>
-              <el-tag type="success" v-if="scope.row.recordStatus === 2" disable-transitions>閫氳繃</el-tag>
-              <el-tag type="danger" v-if="scope.row.recordStatus === 3" disable-transitions>涓嶉�氳繃</el-tag>
-            </template>
-          </el-table-column>
-          <el-table-column label="瀵规瘮鐘舵��" min-width="100" prop="recordContrastStatus">
-            <template #default="scope">
-              <el-tag type="" v-if="scope.row.recordContrastStatus === 0" disable-transitions>鏈紑濮�</el-tag>
-              <el-tag type="warning" v-if="scope.row.recordContrastStatus === 1" disable-transitions>寰呮壒鍑�</el-tag>
-              <el-tag type="success" v-if="scope.row.recordContrastStatus === 2" disable-transitions>閫氳繃</el-tag>
-              <el-tag type="danger" v-if="scope.row.recordContrastStatus === 3" disable-transitions>涓嶉�氳繃</el-tag>
-            </template>
-          </el-table-column>
-          <el-table-column label="澶囨敞" min-width="150" prop="remark"></el-table-column>
-          <!-- 鎿嶄綔鎸夐挳 -->
-          <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="260">
-            <template #default="scope">
-              <el-button size="small" link type="primary" @click="handleForm('edit', scope.row)">缂栬緫</el-button>
-              <el-button size="small" link type="primary" @click="handleForm('view', scope.row)">鏌ョ湅</el-button>
-              <el-button size="small" link type="primary" @click="handleRecord(scope.row)">璁板綍</el-button>
-              <el-button size="small" link type="primary" @click="handleCheck(scope.row)">瀵规瘮</el-button>
-              <el-button size="small" link type="primary" @click="handleDown(scope.row)">瀵煎嚭</el-button>
-              <el-button size="small" link type="danger"
-                @click="deleteFun1(scope.row.planDetailsId)">鍒犻櫎</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
-          :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper" background
-          @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
-        </el-pagination>
-      </div>
+      <el-table ref="yearTableDetailData" v-loading="yearTableDetailDataLoading" :data="yearTableDetailData" border
+        :row-class-name="tableRowClassName" :height="'calc(100vh - 29em)'" style="width: 100%;">
+        <!-- 琛ㄦ牸鍒� -->
+        <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
+          width="70"></el-table-column>
+        <el-table-column label="璁惧缂栧彿" min-width="170" prop="deviceNumber"></el-table-column>
+        <el-table-column label="璁惧鍚嶇О" min-width="180" prop="deviceName" show-overflow-tooltip></el-table-column>
+        <el-table-column label="鏍告煡鏃堕棿" min-width="120" prop="checkTime"
+          :formatter="formatCheckMonth"></el-table-column>
+        <el-table-column label="鏍告煡鎸囨爣" min-width="140" prop="checkIndex"> </el-table-column>
+        <el-table-column label="鏍告煡鏂规硶" min-width="140" prop="checkMethod" show-overflow-tooltip></el-table-column>
+        <el-table-column label="缁撴灉濡備綍鍒ゅ畾" min-width="140" prop="howResults" show-overflow-tooltip></el-table-column>
+        <el-table-column label="鏍告煡璐熻矗浜�" min-width="120" prop="checkChargerUser"></el-table-column>
+        <el-table-column label="璁板綍鐘舵��" min-width="100" prop="recordStatus">
+          <template #default="scope">
+            <el-tag type="" v-if="scope.row.recordStatus === 0" disable-transitions>鏈紑濮�</el-tag>
+            <el-tag type="warning" v-if="scope.row.recordStatus === 1" disable-transitions>寰呮壒鍑�</el-tag>
+            <el-tag type="success" v-if="scope.row.recordStatus === 2" disable-transitions>閫氳繃</el-tag>
+            <el-tag type="danger" v-if="scope.row.recordStatus === 3" disable-transitions>涓嶉�氳繃</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="瀵规瘮鐘舵��" min-width="100" prop="recordContrastStatus">
+          <template #default="scope">
+            <el-tag type="" v-if="scope.row.recordContrastStatus === 0" disable-transitions>鏈紑濮�</el-tag>
+            <el-tag type="warning" v-if="scope.row.recordContrastStatus === 1" disable-transitions>寰呮壒鍑�</el-tag>
+            <el-tag type="success" v-if="scope.row.recordContrastStatus === 2" disable-transitions>閫氳繃</el-tag>
+            <el-tag type="danger" v-if="scope.row.recordContrastStatus === 3" disable-transitions>涓嶉�氳繃</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="澶囨敞" min-width="130" prop="remark"></el-table-column>
+        <!-- 鎿嶄綔鎸夐挳 -->
+        <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="260">
+          <template #default="scope">
+            <el-button size="small" link type="primary" :disabled="planInfo.ratifyStatus === 1"
+              @click="handleForm('edit', scope.row)">缂栬緫</el-button>
+            <el-button size="small" link type="primary" @click="handleForm('view', scope.row)">鏌ョ湅</el-button>
+            <el-button size="small" link type="primary" @click="handleRecord(scope.row)">璁板綍</el-button>
+            <el-button size="small" link type="primary" @click="handleCheck(scope.row)">瀵规瘮</el-button>
+            <el-button size="small" link type="primary" @click="handleDown(scope.row)">瀵煎嚭</el-button>
+            <el-button size="small" link type="danger" :disabled="planInfo.ratifyStatus === 1"
+              @click="deleteFun1(scope.row.planDetailsId)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination :current-page="pagination1.current" :page-size="pagination1.size"
+        :page-sizes="[10, 20, 30, 50, 100]" :total="pagination1.total"
+        layout="->,total, sizes, prev, pager, next, jumper" background
+        @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
+      </el-pagination>
     </div>
     <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible" title="璁惧鏍告煡璁″垝"
       width="80%" @close="resetForm">
@@ -175,7 +139,7 @@
           <el-form-item label="鏍告煡璐d换浜猴細" prop="checkChargerUserId">
             <el-select v-model="form.checkChargerUserId" @change="setCheckChargerUser"
               :disabled="operationType === 'view'" placeholder="璇烽�夋嫨" size="small" style="width: 100%">
-              <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+              <el-option v-for="item in chargerOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
             </el-select>
           </el-form-item>
         </el-col>
@@ -185,10 +149,10 @@
           </el-form-item>
         </el-col>
       </el-form>
-      <template #footer><span  class="dialog-footer">
+      <template #footer><span class="dialog-footer">
         <el-button @click="resetForm">鍙� 娑�</el-button>
-        <el-button :loading="submitFormLoading" type="primary" @click="submitForm" v-if="operationType !== 'view'">纭�
-          璁�</el-button>
+        <el-button :loading="submitFormLoading" type="primary" @click="submitForm"
+          v-if="operationType !== 'view'">纭� 璁�</el-button>
       </span></template>
     </el-dialog>
     <el-dialog v-model="approvalDialog" title="鎵瑰噯" width="30%" @close="approvalDialog = false">
@@ -196,17 +160,19 @@
         鎵瑰噯澶囨敞锛�
         <el-input v-model="ratifyRemark" type="textarea"></el-input>
       </span>
-      <template #footer><span  class="dialog-footer">
+      <template #footer><span class="dialog-footer">
         <el-button :loading="approvalLoading" @click="handleApproval(0)">涓嶆壒鍑�</el-button>
         <el-button :loading="approvalLoading" type="primary" @click="handleApproval(1)">鎵� 鍑�</el-button>
       </span></template>
     </el-dialog>
     <el-dialog v-model="downloadDialog" title="瀵煎嚭" width="600px">
       <span>
-        <el-button :loading="outLoading" type="primary" :disabled="!downRow.recordStatus" @click="controlDown">鏍告煡璁板綍</el-button>
-        <el-button :loading="outLoading" type="primary" :disabled="!downRow.recordContrastStatus" @click="processingDown">鏍告煡姣斿璁板綍</el-button>
+        <el-button :loading="outLoading" type="primary" :disabled="!downRow.recordStatus"
+          @click="controlDown">鏍告煡璁板綍</el-button>
+        <el-button :loading="outLoading" type="primary" :disabled="!downRow.recordContrastStatus"
+          @click="processingDown">鏍告煡姣斿璁板綍</el-button>
       </span>
-      <template #footer><span  class="dialog-footer">
+      <template #footer><span class="dialog-footer">
         <el-button @click="downloadDialog = false">鍙� 娑�</el-button>
       </span></template>
     </el-dialog>
@@ -218,30 +184,26 @@
           </el-option>
         </el-select>
       </span>
-      <template #footer><span  class="dialog-footer">
+      <template #footer><span class="dialog-footer">
         <el-button :loading="notificationLoading" @click="closeNotificationDia">鍙� 娑�</el-button>
         <el-button :loading="notificationLoading" type="primary" @click="notification">鎻� 浜�</el-button>
       </span></template>
     </el-dialog>
     <equipment-check v-if="equipmentCheck" ref="equipmentCheck" @closeDialog="closeDialog"></equipment-check>
     <check-record v-if="checkRecord" ref="checkRecord" @closeDialog1="closeDialog1"></check-record>
-    <add-verification-year-plan-dia v-if="addYearPlanDia" ref="addYearPlanDia"
-      @closeDia="closeDia"></add-verification-year-plan-dia>
   </div>
 </template>
 
 <script>
 import EquipmentCheck from "./equipmentCheck.vue";
 import CheckRecord from "./checkRecord.vue";
-import AddVerificationYearPlanDia from "./addVerificationYearPlanDia.vue";
 import {
   pageDeviceExaminePlan,
+  getExaminePlanByYear,
   submitRatifyDeviceExaminePlan,
   exportDeviceExaminePlanDetail,
-  delDeviceExaminePlan,
   delDeviceExaminePlanDetail,
   pageDeviceExaminePlanDetail,
-  addDeviceExaminePlanDetail,
   updateDeviceExaminePlanDetail,
   ratifyDeviceExaminePlan,
   exportReviewExamineRecordDetail,
@@ -250,10 +212,11 @@
 import { selectUserCondition } from "@/api/performance/class";
 import { mapGetters } from "@/utils/store-compat";
 import draftSave from '@/mixins/draftSave'
+import { formatListDate } from './dateFormat'
 export default {
   name: "equipment-verification-plan",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
-  components: { AddVerificationYearPlanDia, CheckRecord, EquipmentCheck },
+  components: { CheckRecord, EquipmentCheck },
   mixins: [draftSave],
   props: {
     clickNodeVal: {
@@ -266,19 +229,15 @@
   data() {
     // 杩欓噷瀛樻斁鏁版嵁
     return {
-      upLoading: false,
+      planYear: '',
+      yearOptions: [],
+      planInfo: {},
       dialogVisible: false,
       searchForm: {
         deviceName: '',
         deviceNumber: '',
       },
-      yearTableData: [],
       yearTableDetailData: [],
-      pagination: {
-        size: 10,
-        current: 1,
-        total: 0,
-      },
       pagination1: {
         size: 10,
         current: 1,
@@ -302,9 +261,7 @@
         deviceNumber: [{ required: true, message: '璇峰~鍐欒澶囩紪鍙�', trigger: 'blur' }],
         checkMethod: [{ required: true, message: '璇峰~鍐欐牳鏌ユ柟娉�', trigger: 'blur' }],
       },
-      yearTableDataLoading: false,
       yearTableDetailDataLoading: false,
-      currentRow: {},
       approvalDialog: false,
       approvalLoading: false,
       submitFormLoading: false,
@@ -313,7 +270,6 @@
       userList: [],
       equipmentCheck: false,
       checkRecord: false,
-      addYearPlanDia: false,
       downloadDialog: false,
       outLoading: false,
       downRow: {},
@@ -321,60 +277,168 @@
       notificationDia: false,
       notificationLoading: false,
       ratifyUserId: '',
-      planId: ''
     }
   },
   mounted() {
-    this.getYearTableData()
+    this.loadYearOptions()
   },
   // 鏂规硶闆嗗悎
   methods: {
-    // 鏌ヨ骞村害璁″垝琛�
-    getYearTableData() {
-      this.yearTableDataLoading = true
+    // 骞翠唤涓嬫媺閫夐」锛氬凡鏈夎鍒掑勾浠� + 褰撳墠骞翠唤
+    loadYearOptions() {
       pageDeviceExaminePlan({
         current: 1,
         size: 99,
       }).then(res => {
+        let years = []
         if (res.code == 200) {
-          this.yearTableData = res.data.records
-          this.pagination.total = res.data.total
-          if (this.yearTableData.length > 0) {
-            this.currentRow = this.yearTableData[0]
-            this.$refs.yearTable.setCurrentRow(this.currentRow)
-          }
+          years = (res.data.records || []).map(r => r.planYear).filter(Boolean)
         }
-        this.yearTableDataLoading = false
+        const currentYear = String(new Date().getFullYear())
+        if (years.indexOf(currentYear) === -1) {
+          years.push(currentYear)
+        }
+        this.yearOptions = [...new Set(years)].sort((a, b) => b.localeCompare(a))
+        this.planYear = currentYear
+        this.loadPlan()
+      })
+    },
+    // 鍒囨崲骞翠唤
+    handleYearChange() {
+      this.pagination1.current = 1
+      this.loadPlan()
+    },
+    // 鏌ヨ骞翠唤璁″垝锛堜笉瀛樺湪鑷姩鍒涘缓骞惰ˉ鍏ㄥ埌鐐规槑缁嗭級锛岄殢鍚庡埛鏂版槑缁�
+    loadPlan() {
+      getExaminePlanByYear({ planYear: this.planYear }).then(res => {
+        if (res.code == 200) {
+          this.planInfo = res.data || {}
+        }
+        this.getYearTableDetailData()
+      }).catch(() => {
+        this.planInfo = {}
+        this.yearTableDetailData = []
+        this.pagination1.total = 0
+        this.yearTableDetailDataLoading = false
+      })
+    },
+    // 鏌ヨ鏉′欢鍙樺寲鍚庝粠绗竴椤靛紑濮嬫煡
+    handleQuery() {
+      this.pagination1.current = 1
+      this.getYearTableDetailData()
+    },
+    // 鏄庣粏-鏌ヨ
+    getYearTableDetailData() {
+      if (!this.planInfo.planId) {
+        return
+      }
+      this.yearTableDetailDataLoading = true
+      pageDeviceExaminePlanDetail({
+        current: this.pagination1.current,
+        size: this.pagination1.size,
+        planId: this.planInfo.planId,
+        deviceName: this.searchForm.deviceName,
+        deviceNumber: this.searchForm.deviceNumber,
+      }).then(res => {
+        if (res.code == 200) {
+          this.yearTableDetailData = res.data.records
+          this.pagination1.total = res.data.total
+        }
+        this.yearTableDetailDataLoading = false
       }).catch(err => {
-        this.yearTableDataLoading = false
+        this.yearTableDetailDataLoading = false
       })
     },
-    // 鍒嗛〉
-    handleSizeChange(val) {
-      this.pagination.size = val
-      this.getYearTableData()
+    // 鍒扮偣闇�鏍告煡鐨勮鏍囩孩
+    // 鏍告煡鏃堕棿鎸夋湀浠芥樉绀猴紙鍏煎鍘嗗彶鏁版嵁涓殑瀹屾暣鏃ユ湡锛�
+    formatCheckMonth(row, column, cellValue) {
+      if (cellValue === null || cellValue === undefined || cellValue === '') {
+        return cellValue
+      }
+      const str = String(cellValue).trim().replace(/[./]/g, '-')
+      const matched = str.match(/^(\d{4})-(\d{1,2})/)
+      if (matched) {
+        return `${matched[1]}-${matched[2].padStart(2, '0')}`
+      }
+      const formatted = formatListDate(str)
+      const fallback = String(formatted).match(/^(\d{4})-(\d{1,2})/)
+      return fallback ? `${fallback[1]}-${fallback[2].padStart(2, '0')}` : cellValue
+    },
+    tableRowClassName({ row }) {
+      return row.redFlag === 1 ? 'red-row' : ''
+    },
+    reset() {
+      this.searchForm = {
+        deviceName: '',
+        deviceNumber: '',
+      }
+      this.pagination1.current = 1
+      this.getYearTableDetailData()
     },
     // 鍒嗛〉
-    handleCurrentChange(val) {
-      this.pagination.current = val
-      this.getYearTableData()
+    handleSizeChange1(val) {
+      this.pagination1.size = val
+      this.getYearTableDetailData()
     },
-    // 鎵撳紑鏂板寮规
-    addYearPlan(type, row) {
-      this.addYearPlanDia = true
+    // 鍒嗛〉
+    handleCurrentChange1(val) {
+      this.pagination1.current = val
+      this.getYearTableDetailData()
+    },
+    // 鎵撳紑鏄庣粏寮规
+    handleForm(type, row) {
+      this.getUserList()
+      this.operationType = type
+      this.dialogVisible = true
+      this.form.planId = this.planInfo.planId
       this.$nextTick(() => {
-        this.$refs.addYearPlanDia.openDialog(type, row)
+        this.form = this.HaveJson(row)
+        if (this.operationType !== 'view') {
+          this.draftRestore('equipmentVerificationPlan', 'form', this.form.planDetailsId, 'dialogVisible')
+        }
       })
     },
-    closeDia() {
-      this.addYearPlanDia = false
-      this.getYearTableData()
+    // 鎻愪氦琛ㄥ崟
+    submitForm() {
+      this.$refs.modelForm.validate(valid => {
+        if (valid) {
+          this.submitFormLoading = true
+          updateDeviceExaminePlanDetail(this.form).then(res => {
+            if (res.code == 200) {
+              this.$message.success('淇敼鎴愬姛')
+              this.draftClear('equipmentVerificationPlan')
+              this.dialogVisible = false
+              this.getYearTableDetailData()
+            }
+            this.submitFormLoading = false
+          }).catch(err => {
+            this.submitFormLoading = false
+          })
+        }
+      })
+    },
+    // 鏄庣粏-鍒犻櫎
+    deleteFun1(id) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ潯鏄庣粏, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        delDeviceExaminePlanDetail({ planDetailsId: id }).then(res => {
+          this.$message.success('鍒犻櫎鎴愬姛锛�');
+          this.getYearTableDetailData()
+        });
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '宸插彇娑堝垹闄�'
+        });
+      });
     },
     // 鎵撳紑鎻愪氦鎵瑰噯寮规
-    tellApprove(planId) {
+    tellApprove() {
       this.getUserList1()
       this.notificationDia = true
-      this.planId = planId
     },
     // 鍏抽棴鎻愪氦鎵瑰噯寮规
     closeNotificationDia() {
@@ -390,169 +454,23 @@
       this.notificationLoading = true
       submitRatifyDeviceExaminePlan({
         ratifyUserId: this.ratifyUserId,
-        planId: this.planId,
+        planId: this.planInfo.planId,
       }).then(res => {
         this.notificationLoading = false
         if (res.code == 200) {
           this.closeNotificationDia()
-          this.getYearTableData()
+          this.loadPlan()
         }
       }).catch(err => {
         this.notificationLoading = false
       })
     },
-    // 骞村害璁″垝琛�-鎵瑰噯
-    handleApprove(id) {
-      this.currentRowId = id
+    // 鎵瑰噯
+    handleApprove() {
+      this.currentRowId = this.planInfo.planId
       this.approvalDialog = true
     },
-    // 骞村害璁″垝琛�-瀵煎嚭
-    downLoadPost(planId) {
-      exportDeviceExaminePlanDetail({ planId }).then(res => {
-        const blob = new Blob([res], { type: 'application/msword' });
-        this.$download.saveAs(blob, '浠櫒璁惧鏈熼棿鏍告煡璁″垝琛�.docx')
-      })
-    },
-    // 骞村害璁″垝琛�-鍒犻櫎
-    deleteFun(id) {
-      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
-        confirmButtonText: '纭畾',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning'
-      }).then(() => {
-        delDeviceExaminePlan({ planId: id }).then(res => {
-          this.$message.success('鍒犻櫎鎴愬姛锛�');
-          this.getYearTableData();
-        });
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: '宸插彇娑堝垹闄�'
-        });
-      });
-    },
-    // 骞村害璁″垝璇︽儏琛�-鍒犻櫎
-    deleteFun1(id) {
-      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
-        confirmButtonText: '纭畾',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning'
-      }).then(() => {
-        delDeviceExaminePlanDetail({ planDetailsId: id }).then(res => {
-          this.$message.success('鍒犻櫎鎴愬姛锛�');
-          this.getYearTableDetailData(this.currentRow)
-        });
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: '宸插彇娑堝垹闄�'
-        });
-      });
-    },
-    currentChange(row) {
-      this.currentRow = row
-      this.getYearTableDetailData(this.currentRow)
-    },
-    getYearTableDetailData(row) {
-      this.yearTableDetailDataLoading = true
-      pageDeviceExaminePlanDetail({
-        current: this.pagination1.current,
-        size: this.pagination1.size,
-        planId: row.planId,
-        deviceName: this.searchForm.deviceName,
-        deviceNumber: this.searchForm.deviceNumber,
-      }).then(res => {
-        if (res.code == 200) {
-          this.yearTableDetailData = res.data.records
-          this.pagination1.total = res.data.total
-        }
-        this.yearTableDetailDataLoading = false
-      }).catch(err => {
-        this.yearTableDetailDataLoading = false
-      })
-    },
-    reset() {
-      this.searchForm = {
-        deviceName: '',
-        deviceNumber: '',
-      }
-      this.getYearTableDetailData(this.currentRow)
-    },
-    // 鍒嗛〉
-    handleSizeChange1(val) {
-      this.pagination1.size = val
-      this.getYearTableDetailData(this.currentRow)
-    },
-    // 鍒嗛〉
-    handleCurrentChange1(val) {
-      this.pagination1.current = val
-      this.getYearTableDetailData(this.currentRow)
-    },
-    // 鎵撳紑寮规
-    handleForm(type, row) {
-      this.getUserList()
-      this.operationType = type
-      this.dialogVisible = true
-      this.form.planId = this.currentRow.planId
-      if (this.operationType !== 'add') {
-        this.$nextTick(() => {
-          this.form = this.HaveJson(row)
-          if (this.operationType !== 'view') {
-            this.draftRestore('equipmentVerificationPlan', 'form', this.form.planDetailsId, 'dialogVisible')
-          }
-        })
-      } else {
-        this.form = {
-          deviceNumber: '',
-          deviceName: '',
-          checkTime: '',
-          checkIndex: '',
-          checkMethod: '',
-          howResults: '',
-          checkChargerUserId: '',
-          checkChargerUser: '',
-          remark: '',
-          planId: this.currentRow.planId,
-          planDetailsId: '',
-        }
-        this.draftRestore('equipmentVerificationPlan', 'form', this.form.planId, 'dialogVisible')
-      }
-    },
-    // 鎻愪氦琛ㄥ崟
-    submitForm() {
-      this.$refs.modelForm.validate(valid => {
-        if (valid) {
-          if (this.operationType === 'add') {
-            this.submitFormLoading = true
-            addDeviceExaminePlanDetail(this.form).then(res => {
-              if (res.code == 200) {
-                this.$message.success('鏂板鎴愬姛')
-                this.draftClear('equipmentVerificationPlan')
-                this.dialogVisible = false
-                this.getYearTableData()
-              }
-              this.submitFormLoading = false
-            }).catch(err => {
-              this.submitFormLoading = false
-            })
-          } else {
-            this.submitFormLoading = true
-            updateDeviceExaminePlanDetail(this.form).then(res => {
-              if (res.code == 200) {
-                this.$message.success('鏂板鎴愬姛')
-                this.draftClear('equipmentVerificationPlan')
-                this.dialogVisible = false
-                this.getYearTableData()
-              }
-              this.submitFormLoading = false
-            }).catch(err => {
-              this.submitFormLoading = false
-            })
-          }
-        }
-      })
-    },
-    // 鎻愪氦鎵瑰噯
+    // 鎻愪氦鎵瑰噯缁撴灉
     handleApproval(status) {
       const personTrainingUpdateDto = {
         planId: this.currentRowId,
@@ -564,12 +482,18 @@
         if (res.code === 200) {
           this.$message.success('鎻愪氦鎴愬姛锛�');
           this.approvalDialog = false
-          this.getYearTableData();
+          this.loadPlan()
         }
         this.approvalLoading = false
       }).catch(() => {
         this.approvalLoading = false
       })
+    },
+    // 瀵煎嚭骞村害璁″垝琛�
+    downLoadPost() {
+      exportDeviceExaminePlanDetail({ planId: this.planInfo.planId }).then(res => {
+        this.saveDocx(res, '浠櫒璁惧鏈熼棿鏍告煡璁″垝琛�.docx')
+      }).catch(() => { })
     },
     resetForm() {
       this.draftStop('equipmentVerificationPlan')
@@ -586,7 +510,7 @@
     // 鍏抽棴瀵规瘮寮规
     closeDialog() {
       this.equipmentCheck = false
-      this.getYearTableDetailData(this.currentRow)
+      this.getYearTableDetailData()
     },
     // 鎵撳紑璁板綍寮规
     handleRecord(row) {
@@ -598,7 +522,7 @@
     // 鍏抽棴璁板綍寮规
     closeDialog1() {
       this.checkRecord = false
-      this.getYearTableDetailData(this.currentRow)
+      this.getYearTableDetailData()
     },
     // 鎵撳紑瀵煎嚭寮规
     handleDown(row) {
@@ -613,7 +537,7 @@
         const text = (reader.result || '').trim();
         if (text.startsWith('{') || text.startsWith('[')) {
           let msg = '瀵煎嚭澶辫触';
-          try { msg = JSON.parse(text).msg || msg; } catch (e) {}
+          try { msg = JSON.parse(text).msg || msg; } catch (e) { }
           this.$message.error(msg);
         } else {
           this.$download.saveAs(new Blob([res], { type: 'application/msword' }), filename);
@@ -643,30 +567,6 @@
         this.outLoading = false
       })
     },
-    // 瀵煎叆娴佺▼
-    beforeUpload(file) {
-      if (file.size > 1024 * 1024 * 10) {
-        this.$message.error('涓婁紶鏂囦欢涓嶈秴杩�10M');
-        this.$refs.upload.clearFiles()
-        return false;
-      } else {
-        this.upLoading = true;
-        return true;
-      }
-    },
-    onError(err, file, fileList) {
-      this.$message.error('涓婁紶澶辫触')
-      this.$refs.upload.clearFiles()
-    },
-    handleSuccessUp(response) {
-      this.upLoading = false;
-      if (response.code == 200) {
-        this.$message.success('涓婁紶鎴愬姛');
-        this.getYearTableData()
-      } else {
-        this.$message.error(response.message)
-      }
-    },
     getUserList() {
       selectUserCondition().then(res => {
         this.userList = res.data
@@ -687,22 +587,32 @@
       });
     }
   },
-  // 鐢ㄤ簬涓婁紶鏂囦欢鐨勪俊鎭�
   computed: {
-    action() {
-      return this.javaApi + '/deviceExaminePlan/importDeviceExaminePlan'
-    },
     ...mapGetters(["userId"]),
+    // 鏄惁宸插畬鎴愬鎵癸紙鎵瑰噯/涓嶆壒鍑嗭級
+    isRatified() {
+      return this.planInfo.ratifyStatus === 0 || this.planInfo.ratifyStatus === 1;
+    },
+    // 璐d换浜轰笅鎷夛細宸蹭繚瀛樼殑璐d换浜轰笉鍦ㄥ�欓�夊垪琛ㄦ椂琛ヤ竴鏉★紝閬垮厤鍥炴樉鎴愮敤鎴稩D
+    chargerOptions() {
+      const list = this.userList || []
+      const id = this.form.checkChargerUserId
+      if (id && !list.some(item => String(item.id) === String(id))) {
+        return [...list, { id, name: this.form.checkChargerUser || String(id) }]
+      }
+      return list
+    },
   },
 }
 </script>
 
 <style scoped>
 .search {
-  height: 46px;
   display: flex;
   justify-content: space-between;
+  margin-bottom: 10px;
 }
+
 .title {
   position: relative;
   font-size: 16px;
@@ -722,4 +632,33 @@
   background-color: var(--el-color-primary);
   border-radius: 2px;
 }
+
+.plan-top {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  flex-wrap: wrap;
+}
+
+.plan-top-left {
+  display: flex;
+  align-items: center;
+}
+
+.plan-info-bar {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: 32px;
+  background: #f5f7fa;
+  border-radius: 4px;
+  padding: 10px 16px;
+  margin-top: 14px;
+  font-size: 14px;
+  color: #606266;
+}
+
+:deep(.red-row td) {
+  background: #ffcccc !important;
+}
 </style>
diff --git a/src/views/CNAS/resourceDemand/device/component/failureForm.vue b/src/views/CNAS/resourceDemand/device/component/failureForm.vue
index d006a2b..9a7b007 100644
--- a/src/views/CNAS/resourceDemand/device/component/failureForm.vue
+++ b/src/views/CNAS/resourceDemand/device/component/failureForm.vue
@@ -7,7 +7,7 @@
         <el-step title="鐢宠閮ㄩ棬璐熻矗浜烘剰瑙�" @click="setStep(1)"></el-step>
         <el-step title="缁翠慨璁板綍" @click="setStep(2)"></el-step>
       </el-steps>
-      <el-form ref="modelForm" :model="form" :rules="rules" label-width="160px">
+      <el-form ref="modelForm" :model="form" :rules="rules" label-width="160px" :disabled="!canOperate">
         <el-col v-if="showStep === 0" :span="12">
           <el-form-item label="瀹夎鍦扮偣锛�" prop="location">
             <el-input v-model="form.location" :disabled="currentStep !== 0" clearable size="small"></el-input>
@@ -59,7 +59,7 @@
       </el-form>
       <template #footer><span  class="dialog-footer">
         <el-button @click="resetForm">鍙� 娑�</el-button>
-        <el-button v-if="currentStep !== 3" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
+        <el-button v-if="currentStep !== 3 && canOperate" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
           璁�</el-button>
       </span></template>
     </el-dialog>
@@ -72,6 +72,7 @@
   addDeviceBreakdownMaintenance,
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
+import { mapGetters } from "@/utils/store-compat";
 export default {
   name: "failure-form",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -81,6 +82,7 @@
     return {
       dialogVisible: false,
       submitFormLoading: false,
+      canOperate: true,
       form: {
         location: '',
         damageOrMalfunction: '',
@@ -111,6 +113,7 @@
     // 鎵撳紑寮规
     openDialog(id, deviceId) {
       this.dialogVisible = true
+      this.canOperate = true
       this.form.maintenanceId = id
       this.form.deviceId = deviceId
       this.getUserList()
@@ -138,10 +141,23 @@
             this.currentStep = 3
             this.showStep = 2
           }
+          this.applyPermission()
         }
       }).catch(error => {
         console.error(error)
       })
+    },
+    // 闈炲綋鍓嶇幆鑺傝矗浠讳汉鍙厑璁告煡鐪�
+    applyPermission() {
+      if (this.form.isFinish === 1) {
+        this.canOperate = false
+        return
+      }
+      const responsible = this.currentStep === 1 ? this.form.departmentHeadUser : this.form.applicantUser
+      this.canOperate = !responsible || responsible === this.nickName
+      if (!this.canOperate) {
+        this.$message.warning('褰撳墠鐜妭璐d换浜轰负锛�' + responsible + '锛屾偍鍙兘鏌ョ湅')
+      }
     },
     setStep(step) {
       this.showStep = step
@@ -151,6 +167,7 @@
       this.form.flowType = this.currentStep
       this.$refs.modelForm.validate((valid) => {
         if (valid) {
+          this.submitFormLoading = true
           addDeviceBreakdownMaintenance(this.form).then(res => {
             if (res.code == 200) {
               this.$message.success('鏂板鎴愬姛')
@@ -174,6 +191,9 @@
       })
     },
   },
+  computed: {
+    ...mapGetters(["nickName"]),
+  },
 }
 </script>
 
diff --git a/src/views/CNAS/resourceDemand/device/component/fault.vue b/src/views/CNAS/resourceDemand/device/component/fault.vue
index f042ae3..186b7f8 100644
--- a/src/views/CNAS/resourceDemand/device/component/fault.vue
+++ b/src/views/CNAS/resourceDemand/device/component/fault.vue
@@ -31,7 +31,8 @@
           <el-table-column prop="managementNumber" label="缁熶竴缂栧彿" min-width="150"></el-table-column>
           <el-table-column prop="faultSituation" label="鏁呴殰鎯呭喌" min-width="130"></el-table-column>
           <el-table-column prop="submitPerson" label="鎻愪氦浜�" min-width="130"></el-table-column>
-          <el-table-column prop="createTime" label="鎻愪氦鏃ユ湡" min-width="150"></el-table-column>
+          <el-table-column prop="createTime" label="鎻愪氦鏃ユ湡" min-width="150"
+            :formatter="formatDateCell"></el-table-column>
           <el-table-column prop="currentState" label="褰撳墠鐘舵��" min-width="130"></el-table-column>
           <el-table-column prop="currentResponsible" label="褰撳墠璐d换浜�" width="180"></el-table-column>
           <!-- 鎿嶄綔鎸夐挳 -->
@@ -279,6 +280,7 @@
 <script>
 import { dateFormat } from '@/utils/date'
 import { mapGetters } from "@/utils/store-compat";
+import { formatListDate } from './dateFormat'
 export default {
   props: {
     clickNodeVal: {
@@ -318,6 +320,9 @@
     this.getTableList(this.clickNodeVal.value)
   },
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     //瑕佹眰淇鏃ユ湡:绂佺敤鍦ㄦ晠闅滄棩鏈熷墠鐨勬棩鏈�
     disabledDate(time) {
       let selectDate = this.form.faultDate
diff --git a/src/views/CNAS/resourceDemand/device/component/files.vue b/src/views/CNAS/resourceDemand/device/component/files.vue
index 4228c5f..ec28e92 100644
--- a/src/views/CNAS/resourceDemand/device/component/files.vue
+++ b/src/views/CNAS/resourceDemand/device/component/files.vue
@@ -15,12 +15,16 @@
       <el-row :gutter="20">
         <el-col :span="6">
           <!-- 鍔犳椂闂存埑閬垮厤娴忚鍣ㄧ紦瀛橀棶棰� -->
-          <el-image :src="`${javaApi}/img/${Mdata.imageUpload}`" fit="fill" :key="'personalPicture' + timeStamp"
+          <el-image v-if="Mdata.imageUpload" :src="`${javaApi}/img/${Mdata.imageUpload}`" fit="fill" :key="'personalPicture' + timeStamp"
             style="width: 200px;height: 300px;border: 1px solid #000;border-radius: 10px;margin-left: 30px;margin-top: 20px;">
             <template #error><div  class="image-slot">
               <lims-icon name="el-icon-picture-outline" style="font-size: 40px;"></lims-icon>
             </div></template>
           </el-image>
+          <div v-else class="image-slot"
+            style="width: 198px;height: 298px;border: 1px solid #000;border-radius: 10px;margin-left: 30px;margin-top: 20px;display: flex;align-items: center;justify-content: center;">
+            <lims-icon name="el-icon-picture-outline" style="font-size: 40px;"></lims-icon>
+          </div>
         </el-col>
         <el-col :span="8">
           <div class="form-item">
@@ -52,10 +56,6 @@
           </div>
 
           <div class="form-item">
-            <label>鍑哄巶鏃ユ湡</label>
-            <p>{{ formaterDateTime(Mdata.acquisitionDate) }}</p>
-          </div>
-          <div class="form-item">
             <label>鏍″噯鏈夋晥鏈�</label>
             <p>{{ formaterDateTime(Mdata.activationDate) }}</p>
           </div>
@@ -65,19 +65,11 @@
           </div>
 
           <div class="form-item">
-            <label>鎶ュ簾鏃堕棿</label>
-            <p>{{ handleData() }}</p>
-          </div>
-          <div class="form-item">
             <label>鍑嗙‘搴﹂噺鍊�</label>
             <el-tooltip class="item" :content="Mdata.technicalIndicators">
               <span class="text-ellipsis">{{ Mdata.technicalIndicators }}</span>
             </el-tooltip>
             <!-- <p>{{ Mdata.technicalIndicators }}</p> -->
-          </div>
-          <div class="form-item">
-            <label>缁翠慨璁板綍</label>
-            <p>{{ handleData() }}</p>
           </div>
           <div class="form-item">
             <label>琚巿鏉冧汉</label>
@@ -136,15 +128,11 @@
           </div>
           <div class="form-item">
             <label>閲囪喘璐圭敤(鍏�)</label>
-            <p>{{ Mdata.unitPrice }}</p>
+            <p>{{ formatPurchasePrice(Mdata.unitPrice) }}</p>
           </div>
           <div class="form-item">
             <label>璁惧璐熻矗浜�</label>
             <p>{{ Mdata.equipmentManagerName }}</p>
-          </div>
-          <div class="form-item">
-            <label>楠屾敹璁板綍</label>
-            <p>{{ handleData() }}</p>
           </div>
           <div class="form-item">
             <label>鏍稿噯璇佷功</label>
@@ -166,7 +154,7 @@
         <el-table-column prop="quantity" label="浠芥暟" min-width="80" />
         <el-table-column prop="pageCount" label="椤电爜" min-width="80" />
         <el-table-column prop="provider" label="鎻愪緵鑰�" min-width="150" />
-        <el-table-column prop="provideDate" label="褰掓。鏃ユ湡" min-width="170" />
+        <el-table-column prop="provideDate" label="褰掓。鏃ユ湡" min-width="170" :formatter="formatDateCell" />
         <el-table-column prop="comments" label="澶囨敞" min-width="150" />
         <el-table-column fixed="right" label="鎿嶄綔" min-width="180" align="center">
           <template #default="scope">
@@ -185,7 +173,7 @@
       <el-row>
         <el-col :span="7" style="padding-right: 20px;">
           <!-- 鍥剧墖 -->
-          <el-image class="img" style="width:100%;height: 320px;"
+          <el-image v-if="editData.imageUpload" 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;
@@ -197,11 +185,15 @@
               <lims-icon name="el-icon-picture-outline" style="font-size:60px;color:var(--lims-text-2);"></lims-icon>
             </div></template>
           </el-image>
+          <div v-else class="image-error"
+            style="width: calc(100% - 2px);height: 320px;border-radius: 16px;display: flex;align-items: center;justify-content: center;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>
           <!-- 鍥剧墖涓婁紶 -->
           <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"
+              accept='image/jpg,image/jpeg,image/png' :headers="uploadHeader" :before-upload="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>
@@ -276,7 +268,7 @@
               placeholder="璇烽�夋嫨" size="small" style="width:100%;" :collapse-tags="true" separator="," filterable
               clearable></el-cascader>
           </el-form-item>
-          <el-form-item label="璁惧绫诲瀷:">
+          <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>
@@ -319,17 +311,17 @@
         <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 style="width:100%" v-model="editData.lastCalibrationDate" @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 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 :disabled="true" 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-input v-model="editData.calibrationDate" size="small" @change="calcNextDate(editData)"></el-input>
           </el-form-item>
         </div>
         <div class="cycle-row">
@@ -504,6 +496,8 @@
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
 import { selectQualifiedSupplierManagementPage } from '@/api/cnas/externalService/supplierManage/supplierManage'
+import { formatListDate } from './dateFormat'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   props: {
     clickNodeVal: {
@@ -544,7 +538,6 @@
       // },
       fileList: [], // 娣诲姞闄勪欢涓婁紶鏂囦欢鍒楄〃
       timeStamp: '', // 缁欏浘鐗囨坊鍔爇ey锛屽湪姣忔鍔犺浇椤甸潰鐨勬椂鍊欐柊寤烘椂闂存埑
-      equipmentManager: [],
       formLabelWidth: '100px',
       dialogVisible1: false,
       recordNumber: '',
@@ -555,7 +548,7 @@
       num: 1,
       //娣诲姞闄勪欢鏁版嵁鏀堕泦
       addFile: {
-        documentType: '', // 缁存姢绫诲瀷
+        documentType: 0, // 缁存姢绫诲瀷
         provideDate: null, // 褰掓。鏃ユ湡
         name: '', // 妗f鍚嶇О
         number: '', // 搴撳彿/璧勪骇缂栧彿
@@ -577,7 +570,11 @@
       responsiblePersonList: [],
       inspectorList: [],
       options: [],
-      equipmentList: [],
+      // 璁惧绫诲瀷锛氫笌宸︿晶鏍戔�滆澶�/璁¢噺鍣ㄥ叿鈥濆垎绫讳繚鎸佷竴鑷�
+      equipmentList: [
+        { label: '璁惧', value: '璁惧' },
+        { label: '璁¢噺鍣ㄥ叿', value: '璁¢噺鍣ㄥ叿' }
+      ],
       deviceStatusList: [],
       props: { multiple: true, emitPath: false, value: 'id', label: 'name' },
       // 鏀堕泦璁惧妗f鏁版嵁
@@ -612,6 +609,9 @@
     this.obtainQualifiedSupplierList()
   },
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     // 鎷夊彇鍚堟牸渚涘簲鍟嗗垪琛紙鏍″噯鏈嶅姟鏈烘瀯涓嬫媺閫夐」锛�
     obtainQualifiedSupplierList() {
       selectQualifiedSupplierManagementPage({ current: 1, size: 999 }).then(res => {
@@ -662,12 +662,14 @@
     },
     //闄勪欢鍜岀浉鍏虫枃妗d簨浠�
     handleAttachmentClick(row) {
-      console.log(row)
-      if (row.fileName) {
-        this.$download.saveAs(row.fileName)
-      } else {
+      if (!row.systemFileName) {
         this.$message.warning('鏈笂浼犳枃浠讹紒')
+        return
       }
+      // 鍥剧墖瀛� /img/锛屽叾浠栨枃妗e瓨 /word/
+      const isImage = /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(row.systemFileName)
+      const url = this.javaApi + (isImage ? '/img/' : '/word/') + row.systemFileName
+      this.$download.saveAs(url, row.fileName || row.systemFileName)
     },
     handleViewClick(row) {
       this.isAddFileUpdate = true
@@ -701,11 +703,23 @@
       })
     },
     saveRecord() {
+      if (!this.addFile.name) {
+        this.$message.warning('璇疯緭鍏ユ。妗堝悕绉�')
+        return
+      }
+      if (this.addFile.documentType !== 0 && this.addFile.documentType !== '0' &&
+        this.addFile.documentType !== 1 && this.addFile.documentType !== '1') {
+        this.$message.warning('璇烽�夋嫨缁存姢绫诲瀷')
+        return
+      }
       //杞崲鏁版嵁
       this.addFile.deviceId = this.clickNodeVal.value
+      // 鏂颁笂浼犳椂 systemFileName 鏄� {name: 鍘熷鏂囦欢鍚�, url: 瀛樺偍鏂囦欢鍚峿锛涚紪杈戞棫璁板綍鏃跺凡鏄瓧绗︿覆
       let obj = this.addFile.systemFileName
-      this.addFile.systemFileName = obj.name
-      this.addFile.fileName = obj.url
+      if (obj && typeof obj === 'object') {
+        this.addFile.systemFileName = obj.url
+        this.addFile.fileName = obj.name
+      }
 
       // 鏇存柊
       if (this.isAddFileUpdate) {
@@ -737,11 +751,17 @@
       }
     },
     handleRemove(file, fileList) {
-      this.deleteFile(this.addFile.systemFileName)
+      const obj = this.addFile.systemFileName
+      const fileName = obj && typeof obj === 'object' ? obj.url : obj
+      if (fileName) this.deleteFile(fileName)
+      this.addFile.systemFileName = ''
+      this.addFile.fileName = ''
     },
     deleteFile(fileName) {
       deleteCNASFile({ fileName }).then(res => {
-        this.$message.success('鍒犻櫎鎴愬姛锛�')
+        if (res.code == 200) {
+          this.$message.success('鍒犻櫎鎴愬姛锛�')
+        }
       })
     },
     handleExceed(files, fileList) {
@@ -784,7 +804,9 @@
         // 灏嗗垎绫诲垪琛ㄧ殑淇℃伅瀛樿捣鏉�
         if (res.code == 200) {
           this.Mdata = res.data;
-          this.Mdata.insProductIds = this.Mdata.insProductIds.split(',')
+          this.Mdata.insProductIds = this.Mdata.insProductIds
+              ? String(this.Mdata.insProductIds).split(',')
+              : []
           this.Mdata.authorizedPerson = this.normalizeAuthorizedPerson(this.Mdata.authorizedPerson)
         }
       });
@@ -802,6 +824,11 @@
     //鎵撳紑淇妗f寮规
     openEditForm() {
       this.editData = JSON.parse(JSON.stringify(this.Mdata))
+      // 璁惧绫诲瀷涓虹┖鏃讹紝榛樿鍙栧乏渚ф爲褰撳墠鎵�鍦ㄥ垎绫�
+      const treeCategory = this.clickNodeVal && this.clickNodeVal.parent ? this.clickNodeVal.parent.label : ''
+      if (!this.editData.largeCategory && (treeCategory === '璁惧' || treeCategory === '璁¢噺鍣ㄥ叿')) {
+        this.editData.largeCategory = treeCategory
+      }
       this.$nextTick(() => {
         this.dialogVisible = true
       })
@@ -832,55 +859,39 @@
     },
     //淇妗f
     submitForm() {
-      let flag = true
-      this.$refs['rules1'].validate((valid) => {
-        if (!valid) {
-          flag = false;
-          return false;
+      // validate() 杩斿洖 Promise锛岀粺涓�绛夊洓涓〃鍗曞叏閮ㄦ牎楠屽畬鍐嶅垽鏂�
+      const formRefs = ['rules1', 'rules2', 'ruleForm', 'cycleForm']
+      Promise.all(formRefs.map(ref => this.$refs[ref].validate().catch(() => false))).then(results => {
+        if (results.some(valid => !valid)) {
+          return
         }
-      });
-      this.$refs['rules2'].validate((valid) => {
-        if (!valid) {
-          flag = false;
-          return false;
-        }
-      });
-      this.$refs['ruleForm'].validate((valid) => {
-        if (!valid) {
-          flag = false;
-          return false;
-        }
-      });
-      this.$refs['cycleForm'].validate((valid) => {
-        if (!valid) {
-          flag = false;
-          return false;
-        }
-      });
-      if (!flag) {
-        return;
-      }
-      delete this.editData.createTime
-      delete this.editData.updateTime
-      delete this.editData.createUser
-      delete this.editData.updateUser
-      delete this.editData.orderBy
-      const formData = this.HaveJson(this.editData)
-      formData.userAllow = this.equipmentManager.toString();
-      formData.insProductIds = Array.isArray(formData.insProductIds) ? formData.insProductIds.join(',') : '';
-      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.getList(this.clickNodeVal.value)
-        this.dialogVisible = false
-      }).catch(e => {
-        this.$message.error('淇敼澶辫触')
-        this.dialogVisible = false
-        this.upLoad = false
+        delete this.editData.createTime
+        delete this.editData.updateTime
+        delete this.editData.createUser
+        delete this.editData.updateUser
+        delete this.editData.orderBy
+        const formData = this.HaveJson(this.editData)
+        formData.insProductIds = Array.isArray(formData.insProductIds) ? formData.insProductIds.join(',') : '';
+        formData.authorizedPerson = Array.isArray(formData.authorizedPerson) && formData.authorizedPerson.length
+          ? JSON.stringify(formData.authorizedPerson)
+          : ''
+        this.upLoad = true;
+        upDeviceParameter(formData).then(res => {
+          this.upLoad = false
+          if (res.code == 200) {
+            this.$message.success('淇敼鎴愬姛')
+            this.getList(this.clickNodeVal.value)
+            // 绫诲瀷鍙兘鍙樻洿锛屽埛鏂板乏渚ф爲璁╄澶囧綊鍒版柊鐨勫垎绫讳笅
+            this.$emit('refresh-tree')
+            this.dialogVisible = false
+          } else {
+            this.$message.error(res.message || res.msg || '淇敼澶辫触')
+          }
+        }).catch(e => {
+          // 澶辫触淇濈暀寮圭獥锛岄伩鍏嶅凡缂栬緫鍐呭涓㈠け
+          this.$message.error('淇敼澶辫触')
+          this.upLoad = false
+        })
       })
     },
     // 瀵煎嚭
@@ -888,9 +899,18 @@
       this.outLoading = true
       exportDeviceFile({ deviceId: this.clickNodeVal.value }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '璁惧妗f鍗�.doc')
+        saveBlobOrShowError(res, '璁惧妗f鍗�.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
+    },
+    // 淇寮圭獥鎸変竾鍏冨綍鍏ワ紝妗f璇︽儏鎸夊厓灞曠ず
+    formatPurchasePrice(val) {
+      if (val === null || val === undefined || val === '') {
+        return '-'
+      }
+      const num = Number(val)
+      return isNaN(num) ? val : num * 10000
     },
     handleSuccessUpImg2(response) {
       if (response.code == 200) {
@@ -960,10 +980,6 @@
             a.value = parseInt(a.value)
           }
         })
-      });
-      // 璁惧鍒嗙被
-      this.getDicts("device_type").then((response) => {
-        this.equipmentList = this.dictToValue(response.data);
       });
     },
   },
diff --git a/src/views/CNAS/resourceDemand/device/component/inspectionForm.vue b/src/views/CNAS/resourceDemand/device/component/inspectionForm.vue
index e0d8659..effb8fc 100644
--- a/src/views/CNAS/resourceDemand/device/component/inspectionForm.vue
+++ b/src/views/CNAS/resourceDemand/device/component/inspectionForm.vue
@@ -55,7 +55,7 @@
         </el-col>
       </el-row>
       <div>
-        <el-button v-if="operationType === 'add'" size="small" type="primary" @click="addTableRow">娣诲姞</el-button>
+        <el-button v-if="operationType !== 'check'" size="small" type="primary" @click="addTableRow">娣诲姞</el-button>
       </div>
       <div style="text-align: center">娴嬭瘯鏁版嵁璁板綍</div>
       <div style="margin: 10px 0">
@@ -220,7 +220,7 @@
       } else {
         updateDeviceInspectionRecord(this.form).then(res => {
           if (res.code == 200) {
-            this.$message.success('鏂板鎴愬姛')
+            this.$message.success('淇敼鎴愬姛')
             this.resetForm()
           }
           this.submitFormLoading = false
@@ -234,6 +234,7 @@
         inspectionRecordId: this.form.inspectionRecordId,
         status: status,
       }
+      this.submitFormLoading = true
       reviewDeviceInspectionRecord(params).then(res => {
         if (res.code == 200) {
           this.$message.success('瀹℃牳鎴愬姛')
diff --git a/src/views/CNAS/resourceDemand/device/component/inspectionOfEquipment.vue b/src/views/CNAS/resourceDemand/device/component/inspectionOfEquipment.vue
index 1862be0..584bd63 100644
--- a/src/views/CNAS/resourceDemand/device/component/inspectionOfEquipment.vue
+++ b/src/views/CNAS/resourceDemand/device/component/inspectionOfEquipment.vue
@@ -21,7 +21,8 @@
           <el-table-column label="澶嶆牳鐘舵��" min-width="180" prop="status">
             <template #default="scope">
               <el-tag v-if="scope.row.status === 1" type="success">閫� 杩�</el-tag>
-              <el-tag v-if="scope.row.status === 0" type="danger">涓嶉�氳繃</el-tag>
+              <el-tag v-else-if="scope.row.status === 0" type="danger">涓嶉�氳繃</el-tag>
+              <el-tag v-else type="info">寰呭鏍�</el-tag>
             </template>
           </el-table-column>
           <!-- 鎿嶄綔鎸夐挳 -->
@@ -37,7 +38,7 @@
             </template>
           </el-table-column>
         </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
+        <el-pagination :current-page="pagination1.current" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
           :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper" background
           @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
         </el-pagination>
@@ -54,6 +55,7 @@
   exportDeviceInspectionRecord,
   deleteDeviceInspectionRecord,
 } from '@/api/cnas/resourceDemand/device.js'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   name: "inspection-of-equipment",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -127,8 +129,9 @@
         inspectionRecordId: id
       }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '璁惧鐐规璁板綍琛�.doc')
+        saveBlobOrShowError(res, '璁惧鐐规璁板綍琛�.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     // 鍒犻櫎
diff --git a/src/views/CNAS/resourceDemand/device/component/management.vue b/src/views/CNAS/resourceDemand/device/component/management.vue
index 0c7c824..0db1429 100644
--- a/src/views/CNAS/resourceDemand/device/component/management.vue
+++ b/src/views/CNAS/resourceDemand/device/component/management.vue
@@ -27,7 +27,7 @@
         </el-form>
       </div>
       <div>
-        <el-button size="small" type="primary" @click="dialogVisible2 = true">鏂板</el-button>
+        <el-button size="small" type="primary" @click="openAddDialog">鏂板</el-button>
         <el-button size="small" type="primary" @click="handleDownOne">瀵煎嚭</el-button>
       </div>
     </div>
@@ -132,7 +132,7 @@
 							:props="props" placeholder="璇烽�夋嫨" size="small" style="width:100%;" :collapse-tags="!isUp" separator=","
 							filterable clearable></el-cascader>
 					</el-form-item>
-					<el-form-item label="璁惧绫诲瀷:">
+					<el-form-item label="璁惧/璁¢噺鍣ㄥ叿:">
 						<el-select :disabled="isUp" v-model="formData.largeCategory" placeholder="璇烽�夋嫨" size="small"
 							style="width:100%">
 							<el-option v-for="item in equipmentList" :key="item.value" :label="item.label" :value="item.value">
@@ -336,7 +336,7 @@
 							placeholder="璇烽�夋嫨" size="small" style="width:100%" collapse-tags separator="," filterable
 							clearable></el-cascader>
 					</el-form-item>
-					<el-form-item label="璁惧绫诲瀷:">
+					<el-form-item label="璁惧/璁¢噺鍣ㄥ叿:">
 						<el-select v-model="formData2.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>
@@ -425,7 +425,9 @@
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
 import dayjs from 'dayjs'
+import { formatListDate } from './dateFormat'
 import { selectQualifiedSupplierManagementPage } from '@/api/cnas/externalService/supplierManage/supplierManage'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
 	props: {
 		clickNodeVal: {
@@ -473,8 +475,11 @@
 			showData: false, // 鏁伴噰閰嶇疆椤甸潰
 			tableList: [],
 			addDia: true,
-			//璁惧绫诲瀷鍒楄〃
-			equipmentList: [],
+			//璁惧绫诲瀷鍒楄〃锛氫笌宸︿晶鏍戔�滆澶�/璁¢噺鍣ㄥ叿鈥濆垎绫讳繚鎸佷竴鑷�
+			equipmentList: [
+				{ label: '璁惧', value: '璁惧' },
+				{ label: '璁¢噺鍣ㄥ叿', value: '璁¢噺鍣ㄥ叿' }
+			],
 			// 璐熻矗浜哄垪琛�
 			responsiblePersonList: [],
 			// 鎺堟潈浜哄垪琛�
@@ -498,18 +503,18 @@
 				{ label: "鍑哄巶缂栧彿", prop: "factoryNo" },
 				{ label: "绠$悊缂栧彿", prop: "managementNumber" },
 				{ label: "鎶�鏈寚鏍�", prop: "technicalIndicators" },
-				{ label: "璐疆鏃ユ湡", prop: "acquisitionDate" },
-				{ label: "鏍″噯鏈夋晥鏈�", prop: "activationDate" },
+				{ label: "璐疆鏃ユ湡", prop: "acquisitionDate", formatData: (params) => formatListDate(params) },
+				{ label: "鏍″噯鏈夋晥鏈�", prop: "activationDate", formatData: (params) => formatListDate(params) },
 				{ label: "绠$悊浜�", prop: "equipmentManagerUser" },
 				{ label: "瀛樻斁鐐�", prop: "storagePoint" },
 				{ label: "妫�楠岄」鐩�", prop: "insProductItem" },
 				{ label: "鏍″噯鏈嶅姟鏈烘瀯", prop: "calibrationServices" },
-				{ label: "鏈�杩戞牎鍑嗘棩鏈�", prop: "lastCalibrationDateTwo" },
-				{ label: "鏈�杩戞牳鏌ユ棩鏈�", prop: "lastExamineDate" },
-				{ label: "涓嬫鏍″噯鏃ユ湡", prop: "nextCalibrationDateTwo" },
-				{ label: "涓嬫鏍告煡鏃ユ湡", prop: "nextExamineDate" },
-				{ label: "鏈�杩戜繚鍏绘棩鏈�", prop: "lastMaintenanceDate" },
-				{ label: "涓嬫淇濆吇鏃ユ湡", prop: "nextMaintenanceDate" },
+				{ label: "鏈�杩戞牎鍑嗘棩鏈�", prop: "lastCalibrationDateTwo", formatData: (params) => formatListDate(params) },
+				{ label: "鏈�杩戞牳鏌ユ棩鏈�", prop: "lastExamineDate", formatData: (params) => formatListDate(params) },
+				{ label: "涓嬫鏍″噯鏃ユ湡", prop: "nextCalibrationDateTwo", formatData: (params) => formatListDate(params) },
+				{ label: "涓嬫鏍告煡鏃ユ湡", prop: "nextExamineDate", formatData: (params) => formatListDate(params) },
+				{ label: "鏈�杩戜繚鍏绘棩鏈�", prop: "lastMaintenanceDate", formatData: (params) => formatListDate(params) },
+				{ label: "涓嬫淇濆吇鏃ユ湡", prop: "nextMaintenanceDate", formatData: (params) => formatListDate(params) },
 				{
 					label: "璁惧鍒嗙被", prop: "largeCategory", dataType: "tag",
 					formatData: (params) => {
@@ -698,8 +703,9 @@
 			this.outLoading = true
 			exportEquipmentDetails({ ...this.queryParams }).then(res => {
 				this.outLoading = false
-				const blob = new Blob([res], { type: 'application/octet-stream' });
-				this.$download.saveAs(blob, '璁惧浠櫒涓�瑙堣〃.doc')
+				saveBlobOrShowError(res, '璁惧浠櫒涓�瑙堣〃.doc', 'application/msword')
+			}).catch(() => {
+				this.outLoading = false
 			})
 		},
 		// 鑾峰彇瀛楀吀
@@ -707,10 +713,6 @@
 			// 璁惧鐘舵��
 			this.getDicts("device_status").then((response) => {
 				this.deviceStatusList = this.dictToValue(response.data);
-			});
-			// 璁惧鍒嗙被
-			this.getDicts("device_type").then((response) => {
-				this.equipmentList = this.dictToValue(response.data);
 			});
 		},
 		// 鑾峰彇璐熻矗浜哄垪琛�
@@ -812,6 +814,11 @@
 			//澶嶅埗缁檉ormData
 			this.formData = this.HaveJson(row);
 			this.formData.authorizedPerson = this.normalizeAuthorizedPerson(row.authorizedPerson);
+			// 璁惧绫诲瀷涓虹┖鏃讹紝榛樿鍙栧乏渚ф爲褰撳墠鎵�鍦ㄥ垎绫�
+			const treeCategory = this.clickNodeVal && this.clickNodeVal.label
+			if (!this.formData.largeCategory && (treeCategory === '璁惧' || treeCategory === '璁¢噺鍣ㄥ叿')) {
+				this.formData.largeCategory = treeCategory
+			}
 			if (typeof (row.insProductIds) === 'number') {
 				row.insProductIds = row.insProductIds + ''
 			}
@@ -918,6 +925,8 @@
 				this.$message.success('淇敼鎴愬姛')
 				this.upLoad = false
 				this.refreshTable('page')
+				// 绫诲瀷鍙兘鍙樻洿锛屽埛鏂板乏渚ф爲璁╄澶囧綊鍒版柊鐨勫垎绫讳笅
+				this.$emit('refresh-tree')
 				this.dialogVisible = false
 			}).catch(e => {
 				this.$message.error('淇敼澶辫触')
@@ -937,6 +946,10 @@
 			}
 			if (!this.formData2.managementNumber) {
 				this.$message.error('鏈緭鍏ョ鐞嗙紪鍙�')
+				return
+			}
+			if (!this.formData2.largeCategory) {
+				this.$message.error('璇烽�夋嫨璁惧/璁¢噺鍣ㄥ叿')
 				return
 			}
 			if (!this.formData2.activationDate) {
@@ -961,6 +974,7 @@
 				this.$message.success('鎻愪氦鎴愬姛')
 				this.upLoad2 = false
 				this.refreshTable('page')
+				this.$emit('refresh-tree')
 				this.dialogVisible2 = false
 				this.formData2 = {
 					imageUpload: '',
@@ -1006,6 +1020,14 @@
 				this.refreshTable('page')
 			}
 		},
+		// 鏂板璁惧锛氶粯璁ゅ彇宸︿晶鏍戝綋鍓嶆墍鍦ㄥ垎绫�
+		openAddDialog() {
+			const treeCategory = this.clickNodeVal && this.clickNodeVal.label
+			if (!this.formData2.largeCategory && (treeCategory === '璁惧' || treeCategory === '璁¢噺鍣ㄥ叿')) {
+				this.formData2.largeCategory = treeCategory
+			}
+			this.dialogVisible2 = true
+		},
 		handleDelete(row) {
 			this.$confirm("鏄惁鍒犻櫎璇ユ潯鏁版嵁?", "鎻愮ず", {
 				confirmButtonText: "纭畾",
@@ -1015,7 +1037,9 @@
 				.then(() => {
 					delDeviceParameter({ id: row.id }).then((res) => {
 						this.$message.success("鍒犻櫎鎴愬姛");
-						this.refresh();
+						this.refreshTable()
+						// 宸插垹闄ょ殑璁惧瑕佷粠宸︿晶鏍戝悓姝ョЩ闄�
+						this.$emit('refresh-tree')
 					});
 				})
 				.catch(() => { });
diff --git a/src/views/CNAS/resourceDemand/device/component/operationInstruction.vue b/src/views/CNAS/resourceDemand/device/component/operationInstruction.vue
index c373600..fbf1483 100644
--- a/src/views/CNAS/resourceDemand/device/component/operationInstruction.vue
+++ b/src/views/CNAS/resourceDemand/device/component/operationInstruction.vue
@@ -17,11 +17,12 @@
       <el-table-column label="璁惧缂栧彿" min-width="150" prop="deviceNumber"></el-table-column>
       <el-table-column label="璁惧鍨嬪彿" min-width="150" prop="deviceModel"></el-table-column>
       <el-table-column label="鏂囦欢缂栧彿" min-width="150" prop="documentNumber"></el-table-column>
-      <el-table-column label="鏂囦欢鍚嶅瓧" min-width="150" prop="fileName"></el-table-column>
+      <el-table-column label="鏂囦欢鍚嶇О" min-width="150" prop="fileName"></el-table-column>
       <el-table-column label="鏂囨。璇存槑" min-width="150" prop="documentNote"></el-table-column>
       <el-table-column label="涓婁紶浜�" min-width="150" prop="uploaderName"></el-table-column>
-      <el-table-column label="涓婁紶鏃堕棿" min-width="150" prop="updateTime"></el-table-column>
-      <el-table-column label="鐢熸晥鏃堕棿" min-width="150" prop="entryIntoForceTime"></el-table-column>
+      <el-table-column label="涓婁紶鏃堕棿" min-width="150" prop="updateTime" :formatter="formatDateCell"></el-table-column>
+      <el-table-column label="鐢熸晥鏃堕棿" min-width="150" prop="entryIntoForceTime"
+        :formatter="formatDateCell"></el-table-column>
       <el-table-column label="瀹℃壒浜�" min-width="150" prop="approverName"></el-table-column>
       <el-table-column label="瀹℃壒鐘舵��" min-width="150" prop="status">
         <template v-slot="scope">
@@ -31,14 +32,16 @@
       <el-table-column label="鎿嶄綔" min-width="180" fixed="right" prop="name">
         <template v-slot="scope">
           <el-button link type="primary" size="small" @click="downloadFile(scope.row.fileSystemName)">涓嬭浇</el-button>
-          <el-button link type="primary" size="small" style="color: red;"
+          <el-button link type="primary" size="small" style="color: red;" :disabled="scope.row.status === true"
             @click="deleteHomeworkGuidebook(scope.row)">鍒犻櫎</el-button>
-          <el-button link type="primary" size="small" @click="instructionEditFun(scope.row)">缂栬緫</el-button>
-          <el-button link type="primary" size="small" @click="approval(scope.row)">瀹℃壒</el-button>
+          <el-button link type="primary" size="small" :disabled="scope.row.status === true"
+            @click="instructionEditFun(scope.row)">缂栬緫</el-button>
+          <el-button link type="primary" size="small" :disabled="scope.row.status === true"
+            @click="approval(scope.row)">瀹℃壒</el-button>
         </template>
       </el-table-column>
     </el-table>
-    <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="1"
+    <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="search.current"
       :page-sizes="[10, 20, 30, 50, 100]" :page-size="search.size" layout="->,total, sizes, prev, pager, next, jumper"
       :total="search.total" background>
     </el-pagination>
@@ -82,7 +85,7 @@
         <el-table :data="documentTableData" border style="width: 100%;" tooltip-effect="dark" :row-key="getRowKey"
 
           @selection-change="handleSelectionChange" height="29em">
-          <el-table-column type="selection" width="55%">
+          <el-table-column type="selection" width="55">
           </el-table-column>
           <el-table-column label="搴忓彿" prop="id" type="index" width="60"></el-table-column>
           <el-table-column label="璁惧鍚嶇О" prop="deviceName" show-overflow-tooltip min-width="125"></el-table-column>
@@ -91,7 +94,8 @@
           <el-table-column label="鏂囨。缂栧彿" prop="documentNumber" show-overflow-tooltip min-width="125"></el-table-column>
           <el-table-column label="鏂囦欢鍚嶇О" prop="fileName" show-overflow-tooltip min-width="125"></el-table-column>
           <el-table-column label="涓婁紶浜�" prop="author" show-overflow-tooltip min-width="125"></el-table-column>
-          <el-table-column label="涓婁紶鏃堕棿" prop="updateTime" show-overflow-tooltip min-width="125"></el-table-column>
+          <el-table-column label="涓婁紶鏃堕棿" prop="updateTime" show-overflow-tooltip min-width="125"
+            :formatter="formatDateCell"></el-table-column>
           <el-table-column min-width="100" label="鎿嶄綔" fixed="right">
             <template v-slot="scope">
               <el-button link type="primary" size="small" @click="downloadFile(scope.row.fileSystemName)">涓嬭浇</el-button>
@@ -188,6 +192,7 @@
   pageByPageQueryOfHomeworkInstructions,
   selectDeviceParameter,
 } from '@/api/cnas/resourceDemand/device.js'
+import { formatListDate } from './dateFormat'
 export default {
   props: {
     clickNodeVal: {
@@ -266,6 +271,9 @@
     }
   },
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     approval(row) {
       this.$confirm('鏄惁瀹℃壒閫氳繃锛�', '鎻愮ず', {
         confirmButtonText: '閫氳繃',
@@ -273,8 +281,11 @@
         type: 'warning'
       }).then(() => {
         this.approvalFun(row.id, true)
-      }).catch(() => {
-        this.approvalFun(row.id, false)
+      }).catch((action) => {
+        // 鍙湁鐐瑰嚮鈥滀笉閫氳繃鈥濇墠鎻愪氦椹冲洖锛岀偣鍙充笂瑙掑叧闂�/Esc 瑙嗕负鏀惧純鎿嶄綔
+        if (action === 'cancel') {
+          this.approvalFun(row.id, false)
+        }
       });
     },
     approvalFun(id, status) {
@@ -329,9 +340,9 @@
       homeworkGuidebookEditor({ instructionId: row.instructionId }).then(res => {
         if (res.code == 200) {
           this.instructionForm = res.data.instruction;
-          if (this.instructionForm.fileSystemName) {
-            this.fileList1.push({ name: this.instructionForm.fileName })
-          }
+          this.fileList1 = this.instructionForm.fileSystemName
+            ? [{ name: this.instructionForm.fileName }]
+            : []
           this.documentTableData = res.data.list;
           // 鍒犻櫎鐢�
           this.documentTableData.forEach((v, k) => {
@@ -402,6 +413,7 @@
             this.$message.success('淇敼鎴愬姛');
             console.log('this.documentTableData---edit', this.documentTableData[this.tableDataIndex])
           } else {
+            this.form.index = this.getNextRowIndex();
             this.documentTableData.push(this.form);
             this.dialogVisible1 = false;
             this.$message.success('娣诲姞鎴愬姛');
@@ -423,12 +435,17 @@
     editFun(row, index) {
       this.form = { ...row }
       this.tableDataIndex = index;
-      console.log('this.tableDataIndex', this.tableDataIndex)
-      // 鍥炴樉鍒楄〃
+      // 鍥炴樉鍒楄〃鍓嶅厛娓呯┖锛岄伩鍏嶉噸澶嶆樉绀轰笂涓�娆$殑闄勪欢
+      this.fileList = []
       if (this.form.fileSystemName) {
         this.fileList.push({ name: this.form.fileName })
       }
       this.dialogVisible1 = true
+    },
+    getNextRowIndex() {
+      return this.documentTableData.reduce((max, item) => {
+        return typeof item.index === 'number' && item.index > max ? item.index : max
+      }, -1) + 1
     },
     closeDia() {
       this.dialogVisible1 = false
@@ -443,22 +460,24 @@
         this.$message.error('璇烽�夋嫨瑕佸垹闄ょ殑閫夐」');
         return;
       }
-      // 鍒犻櫎淇濆瓨濂界殑鏁版嵁
-      let ids = this.selectedRow
+      const selectedIndexes = this.selectedRow.map(item => item.index);
+      // 鍒犻櫎宸蹭繚瀛樼殑鏁版嵁锛涙湰娆℃柊鍔犮�佸皻鏈惤搴撶殑琛屾病鏈� id锛屼笉璋冩帴鍙�
+      const ids = this.selectedRow
         .filter(item => item.id !== undefined)
         .map(item => item.id).join(',');
-      //鏈夐敊璇�
-      const res = await deleteHomeworkGuidebook({ ids });
-      if (res.code === 200) {
-        // 鍒犻櫎瑙嗗浘鐨勬暟鎹�
-        for (const resKey in this.selectedRow) {
-          this.documentTableData = this.documentTableData.filter(item => item.index === this.selectedRow[resKey].index)
+      if (ids) {
+        const res = await deleteHomeworkGuidebook({ ids });
+        if (res.code !== 200) {
+          return;
         }
-        this.$message.success({
-          message: '鍒犻櫎鎴愬姛',
-          type: 'success'
-        });
       }
+      // 涓�娆℃�ц繃婊ゆ帀鎵�鏈夐�変腑琛岋紝淇濈暀鍏朵綑鏁版嵁
+      this.documentTableData = this.documentTableData.filter(item => !selectedIndexes.includes(item.index))
+      this.selectedRow = []
+      this.$message.success({
+        message: '鍒犻櫎鎴愬姛',
+        type: 'success'
+      });
     },
     onSuccess(response, file, fileList) {
       this.form.fileName = file.name;
@@ -476,8 +495,8 @@
       this.form.fileSystemName = ''
     },
     handleRemove1(file, fileList) {
-      this.form.fileName = ''
-      this.form.fileSystemName = ''
+      this.instructionForm.fileName = ''
+      this.instructionForm.fileSystemName = ''
     },
     beforeRemove(file) {
       return this.$confirm(`纭畾绉婚櫎 ${file.name}锛焋)
@@ -486,7 +505,12 @@
       this.$message.warning(`褰撳墠闄愬埗閫夋嫨 1 涓枃浠讹紝鏈閫夋嫨浜� ${files.length} 涓枃浠躲�俙);
     },
     getList() {
-      pageByPageQueryOfHomeworkInstructions({ ...this.search }).then(res => {
+      const params = { ...this.search }
+      // 閫変腑鍏蜂綋璁惧鏃跺彧鏌ヨ璁惧鐨勪綔涓氭寚瀵间功
+      if (this.clickNodeVal && this.clickNodeVal.value) {
+        params.deviceId = this.clickNodeVal.value
+      }
+      pageByPageQueryOfHomeworkInstructions(params).then(res => {
         if (res.code == 200) {
           this.tableData = res.data.records;
           this.search.total = res.data.total
diff --git a/src/views/CNAS/resourceDemand/device/component/quantityValueTraceabilityPlan.vue b/src/views/CNAS/resourceDemand/device/component/quantityValueTraceabilityPlan.vue
index 5c48070..fd36b81 100644
--- a/src/views/CNAS/resourceDemand/device/component/quantityValueTraceabilityPlan.vue
+++ b/src/views/CNAS/resourceDemand/device/component/quantityValueTraceabilityPlan.vue
@@ -15,7 +15,8 @@
           <el-table-column label="骞翠唤" min-width="80" prop="planYear"></el-table-column>
           <el-table-column label="鏂囦欢鍚嶇О" min-width="120" prop="compiler"></el-table-column>
           <el-table-column label="缂栧埗浜�" min-width="150" prop="compiler"></el-table-column>
-          <el-table-column label="缂栧埗鏃堕棿" min-width="160" prop="datePreparation"></el-table-column>
+          <el-table-column label="缂栧埗鏃堕棿" min-width="160" prop="datePreparation"
+            :formatter="formatDateCell"></el-table-column>
           <el-table-column label="鎵瑰噯浜�" min-width="180" prop="audit"></el-table-column>
           <el-table-column label="鎵瑰噯鐘舵��" min-width="180" prop="status">
             <template #default="scope">
@@ -23,7 +24,8 @@
               <el-tag v-if="scope.row.status === 0" type="danger">涓嶆壒鍑�</el-tag>
             </template>
           </el-table-column>
-          <el-table-column label="鎵瑰噯鏃堕棿" min-width="180" prop="auditDate"></el-table-column>
+          <el-table-column label="鎵瑰噯鏃堕棿" min-width="180" prop="auditDate"
+            :formatter="formatDateCell"></el-table-column>
           <!-- 鎿嶄綔鎸夐挳 -->
           <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="270">
             <template #default="scope">
@@ -174,6 +176,7 @@
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
 import { mapGetters } from "@/utils/store-compat";
+import { formatListDate } from './dateFormat'
 export default {
   name: "quantity-value-traceability-plan",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -220,6 +223,9 @@
   },
   // 鏂规硶闆嗗悎
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     // 鏌ヨ
     getYearTableDetailData() {
       this.yearTableDetailDataLoading = true
diff --git a/src/views/CNAS/resourceDemand/device/component/record.vue b/src/views/CNAS/resourceDemand/device/component/record.vue
index 1ef3cd1..9c45784 100644
--- a/src/views/CNAS/resourceDemand/device/component/record.vue
+++ b/src/views/CNAS/resourceDemand/device/component/record.vue
@@ -17,7 +17,7 @@
         </el-form-item>
       </el-form>
       <div>
-        <el-button size="small" type="primary" @click="dialogVisible = true, openAdd()">鏂� 寤�</el-button>
+        <el-button v-if="isMenuList !== 1" size="small" type="primary" @click="dialogVisible = true, openAdd()">鏂� 寤�</el-button>
         <el-button :loading="outLoading" size="small" type="primary" @click="openHandleOut">瀵� 鍑�</el-button>
       </div>
     </div>
@@ -45,8 +45,8 @@
           </template>
         </el-table-column>
         <!--        <el-table-column label="寮傚父鎯呭喌" min-width="120" prop="abnormal" />-->
-        <el-table-column label="浣跨敤寮�濮嬫棩鏈�" min-width="170" prop="useStartDate" />
-        <el-table-column label="浣跨敤缁撴潫鏃ユ湡" min-width="170" prop="useEndDate" />
+        <el-table-column label="浣跨敤寮�濮嬫棩鏈�" min-width="170" prop="useStartDate" :formatter="formatDateCell" />
+        <el-table-column label="浣跨敤缁撴潫鏃ユ湡" min-width="170" prop="useEndDate" :formatter="formatDateCell" />
         <el-table-column label="浣跨敤浜�" min-width="120" prop="usePerson" />
         <el-table-column label="澶囨敞" min-width="120" prop="remark" />
         <!-- 鎿嶄綔鎸夐挳 -->
@@ -58,7 +58,7 @@
           </template>
         </el-table-column>
       </el-table>
-      <el-pagination :current-page="1" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
+      <el-pagination :current-page="search.current" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
         :total="search.total" layout="->,total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
         @current-change="handleCurrentChange" background>
       </el-pagination>
@@ -157,6 +157,8 @@
   deleteDeviceRecord,
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
+import { formatListDate } from './dateFormat';
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   props: {
     clickNodeVal: {
@@ -221,6 +223,9 @@
     this.getTableList(this.clickNodeVal.value);
   },
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     // element-plus 鐨� el-date-picker 娌℃湁 picker-options锛屾敼鎴� :disabled-date
     disabledDate(time) {
       return time.getTime() > Date.now();
@@ -275,8 +280,9 @@
         exportDate: this.exportDate
       }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '璁惧浣跨敤璁板綍.doc')
+        saveBlobOrShowError(res, '璁惧浣跨敤璁板綍.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     //鏂板缓
@@ -312,7 +318,6 @@
                 this.dialogVisible = false
               }
             })
-            this.dialogVisible = false;
           } else {
             updateDeviceRecord(this.form).then(res => {
               if (res.code == 200) {
@@ -321,7 +326,6 @@
                 this.dialogVisible = false
               }
             })
-            this.dialogVisible = false;
           }
         }
       });
@@ -329,20 +333,17 @@
     //鏌ョ湅璇︽儏
     showDetailsDialog(type, row) {
       this.operationType = type;
-      console.log(row)
       this.dialogVisible = true;
       this.getUserList()
-      this.form = row;
-      let list = []
-      if (row.useStartDate === null) {
-        row.useStartDate = ''
+      // 澶嶅埗涓�浠藉啀缂栬緫锛岄伩鍏嶇洿鎺ユ敼鍔ㄨ〃鏍奸噷鐨勬暟鎹�
+      const useStartDate = row.useStartDate || ''
+      const useEndDate = row.useEndDate || ''
+      this.form = {
+        ...row,
+        useStartDate,
+        useEndDate,
+        useDateList: useStartDate && useEndDate ? [useStartDate, useEndDate] : []
       }
-      if (row.useEndDate === null) {
-        row.useEndDate = ''
-      }
-      list.push(row.useStartDate)
-      list.push(row.useEndDate)
-      this.form['useDateList'] = list
     },
     handleDeleteClick(index, row) {
       this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
diff --git a/src/views/CNAS/resourceDemand/device/component/scrapApplicationForm.vue b/src/views/CNAS/resourceDemand/device/component/scrapApplicationForm.vue
index 5e4bfcf..7b40798 100644
--- a/src/views/CNAS/resourceDemand/device/component/scrapApplicationForm.vue
+++ b/src/views/CNAS/resourceDemand/device/component/scrapApplicationForm.vue
@@ -8,7 +8,7 @@
         <el-step title="璁¢噺瀹ゆ剰瑙�" @click="setStep(2)"></el-step>
         <el-step title="鎵瑰噯浜�" @click="setStep(3)"></el-step>
       </el-steps>
-      <el-form ref="modelForm" :model="form" :rules="rules" label-width="160px">
+      <el-form ref="modelForm" :model="form" :rules="rules" label-width="160px" :disabled="!canOperate">
         <el-col v-if="showStep === 0" :span="24">
           <el-form-item label="閰嶄欢锛�" prop="parts">
             <el-input v-model="form.parts" :disabled="currentStep !== 0" clearable size="small"></el-input>
@@ -65,7 +65,7 @@
       </el-form>
       <template #footer><span  class="dialog-footer">
         <el-button @click="resetForm">鍙� 娑�</el-button>
-        <el-button v-if="currentStep !== 4" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
+        <el-button v-if="currentStep !== 4 && canOperate" :loading="submitFormLoading" type="primary" @click="submitForm">纭�
           璁�</el-button>
       </span></template>
     </el-dialog>
@@ -78,6 +78,7 @@
   addDeviceScrapped,
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/business/inspectionTask";
+import { mapGetters } from "@/utils/store-compat";
 export default {
   name: "scrapApplicationForm",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -87,6 +88,7 @@
     return {
       dialogVisible: false,
       submitFormLoading: false,
+      canOperate: true,
       form: {
         parts: '',
         reasonsForScrap: '',
@@ -118,6 +120,7 @@
     // 鎵撳紑寮规
     openDialog(id, deviceId) {
       this.dialogVisible = true
+      this.canOperate = true
       this.form.scrappedId = id
       this.form.deviceId = deviceId
       this.getUserList()
@@ -149,10 +152,29 @@
             this.currentStep = 4
             this.showStep = 3
           }
+          this.applyPermission()
         }
       }).catch(error => {
         console.error(error)
       })
+    },
+    // 闈炲綋鍓嶇幆鑺傝矗浠讳汉鍙厑璁告煡鐪�
+    applyPermission() {
+      if (this.form.isFinish === 1 || this.currentStep >= 4) {
+        this.canOperate = false
+        return
+      }
+      const responsibleList = [
+        this.form.applicantUser,
+        this.form.departmentHeadUser,
+        this.form.meteringRoomUser,
+        this.form.approverUser,
+      ]
+      const responsible = responsibleList[this.currentStep]
+      this.canOperate = !responsible || responsible === this.nickName
+      if (!this.canOperate) {
+        this.$message.warning('褰撳墠鐜妭璐d换浜轰负锛�' + responsible + '锛屾偍鍙兘鏌ョ湅')
+      }
     },
     setStep(step) {
       this.showStep = step
@@ -162,6 +184,7 @@
       this.form.flowType = this.currentStep
       this.$refs.modelForm.validate((valid) => {
         if (valid) {
+          this.submitFormLoading = true
           addDeviceScrapped(this.form).then(res => {
             if (res.code == 200) {
               this.$message.success('鏂板鎴愬姛')
@@ -185,6 +208,9 @@
       })
     },
   },
+  computed: {
+    ...mapGetters(["nickName"]),
+  },
 }
 </script>
 
diff --git a/src/views/CNAS/resourceDemand/device/component/state.vue b/src/views/CNAS/resourceDemand/device/component/state.vue
index 15f53ba..b739fdf 100644
--- a/src/views/CNAS/resourceDemand/device/component/state.vue
+++ b/src/views/CNAS/resourceDemand/device/component/state.vue
@@ -13,7 +13,7 @@
         </el-form-item>
       </el-form>
       <div>
-        <el-button size="small" type="primary" @click="dialogVisible = true">鏂板缓</el-button>
+        <el-button size="small" type="primary" @click="handleAddClick">鏂板缓</el-button>
         <el-button :loading="outLoading" size="small" type="primary" @click="handleDown">瀵煎嚭Excel</el-button>
       </div>
     </div>
@@ -33,7 +33,8 @@
         </el-table-column>
         <el-table-column label="鍋滅敤/鍚敤鐞嗙敱" min-width="180" prop="reason"></el-table-column>
         <el-table-column label="鎻愪氦浜�" min-width="130" prop="createUser"></el-table-column>
-        <el-table-column label="鎻愪氦鏃ユ湡" min-width="150" prop="createTime"></el-table-column>
+        <el-table-column label="鎻愪氦鏃ユ湡" min-width="150" prop="createTime"
+          :formatter="formatDateCell"></el-table-column>
         <el-table-column label="褰撳墠鐘舵��" min-width="130" prop="currentState"></el-table-column>
         <el-table-column label="褰撳墠璐d换浜�" min-width="180" prop="currentResponsible"></el-table-column>
         <!-- 鎿嶄綔鎸夐挳 -->
@@ -45,7 +46,7 @@
           </template>
         </el-table-column>
       </el-table>
-      <el-pagination :current-page="1" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
+      <el-pagination :current-page="search.current" :page-size="search.size" :page-sizes="[10, 20, 30, 50, 100]"
         :total="search.total" layout="->,total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
         @current-change="handleCurrentChange" background>
       </el-pagination>
@@ -56,7 +57,7 @@
         <el-step v-for="(v, i) in steps" :key="i" :title="v" style="cursor:pointer"
           @click="choiceStep(i)"></el-step>
       </el-steps>
-      <el-form ref="form" :model="form" :rules="rules" label-width="130px">
+      <el-form ref="form" :model="form" :rules="rules" label-width="130px" :disabled="!canOperate">
         <div v-show="currentStepClick === 0">
           <el-card style="margin-top: 1em; height: 42vh; overflow-y: scroll;">
             <!-- 鍗$墖 -->
@@ -220,10 +221,10 @@
         </div>
       </el-form>
       <template #footer><span  class="dialog-footer">
-        <el-button v-if="currentStep !== 0 && currentStep !== 4" :loading="sumbitLoading1"
+        <el-button v-if="currentStep !== 0 && currentStep !== 4 && canOperate" :loading="sumbitLoading1"
           @click="submitForm('3reject')">椹冲洖</el-button>
-        <el-button v-if="currentStep === 0" :loading="sumbitLoading2" @click="submitForm('2save')">淇濆瓨</el-button>
-        <el-button v-if="currentStep !== 4" :loading="sumbitLoading3" type="primary" @click="submitForm('1submit')">
+        <el-button v-if="currentStep === 0 && canOperate" :loading="sumbitLoading2" @click="submitForm('2save')">淇濆瓨</el-button>
+        <el-button v-if="currentStep !== 4 && canOperate" :loading="sumbitLoading3" type="primary" @click="submitForm('1submit')">
           {{ currentStep === 0 ? '鎻愪氦' : '閫氳繃' }}
         </el-button>
       </span></template>
@@ -242,6 +243,8 @@
 import { selectUserCondition } from "@/api/business/inspectionTask";
 import { dateFormat } from '@/utils/date'
 import { mapGetters } from "@/utils/store-compat";
+import { formatListDate } from './dateFormat'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   props: {
     clickNodeVal: {
@@ -258,6 +261,7 @@
     return {
       outLoading: false, // 瀵煎嚭loading
       dialogVisible: false,
+      canOperate: true,
       form: {},
       currentStep: 0, // 姝ラ鏉℃樉绀虹鍑犳
       currentStepClick: 0, // 鐐瑰嚮姝ラ鏉″彉鍖�
@@ -282,6 +286,9 @@
     this.getDeviceStatePage(this.clickNodeVal.value)
   },
   methods: {
+    formatDateCell(row, column, cellValue) {
+      return formatListDate(cellValue)
+    },
     // 鍒嗛〉
     handleSizeChange(val) {
       this.search.size = val
@@ -341,22 +348,40 @@
             default:
               break
           }
-          // 鑾峰彇褰撳墠鐜妭璐熻矗浜�
-          switch (saveState === '3reject' ? this.currentStep - 1 : this.currentStep) {
-            case 0:
-              this.form.currentResponsible = this.form.submitOperatingPersonnel
-              break
-            case 1:
-              this.form.currentResponsible = this.form.departmentOperatingPersonnel
-              break
-            case 2:
-              this.form.currentResponsible = this.form.measuringRoomOperatingPersonnel
-              break
-            case 3:
-              this.form.currentResponsible = this.form.approvalOperatingPersonnel
-              break
-            default:
-              break
+          // 鑾峰彇褰撳墠鐜妭璐熻矗浜猴細椹冲洖鍥炲埌涓婁竴鐜妭鎿嶄綔浜猴紝淇濆瓨鐣欑粰鑷繁锛屾彁浜�/閫氳繃杩涘叆涓嬩竴鐜妭璐d换浜�
+          if (saveState === '3reject') {
+            switch (this.currentStep - 1) {
+              case 0:
+                this.form.currentResponsible = this.form.submitOperatingPersonnel
+                break
+              case 1:
+                this.form.currentResponsible = this.form.departmentOperatingPersonnel
+                break
+              case 2:
+                this.form.currentResponsible = this.form.measuringRoomOperatingPersonnel
+                break
+              default:
+                break
+            }
+          } else if (saveState === '2save') {
+            this.form.currentResponsible = this.form.submitOperatingPersonnel
+          } else {
+            switch (this.currentStep) {
+              case 0:
+                this.form.currentResponsible = this.form.submitNextPesponsible
+                break
+              case 1:
+                this.form.currentResponsible = this.form.departmentNextPesponsible
+                break
+              case 2:
+                this.form.currentResponsible = this.form.measuringRoomNextPesponsible
+                break
+              case 3:
+                this.form.currentResponsible = this.form.approvalNextPesponsible
+                break
+              default:
+                break
+            }
           }
           // 鑾峰彇褰撳墠鐘舵��
           this.form.currentState = currentStepAction === 4 ? '鍏抽棴' : this.steps[currentStepAction]
@@ -406,24 +431,43 @@
         }
       })
     },
+    // 鏂板缓
+    handleAddClick() {
+      this.canOperate = true
+      this.dialogVisible = true
+    },
     // 鏌ョ湅
     handleViewClick(row) {
       this.form = { ...row }
       // 濡傛灉绱㈠紩涓�6琛ㄧず鍏ㄩ儴閫氳繃
       this.currentStep = this.steps.indexOf(this.form.currentState) === -1 ? 4 : this.steps.indexOf(this.form.currentState)
       this.currentStepClick = this.currentStep === 4 ? 0 : this.currentStep
-      this.$nextTick(() => {
-        this.$refs['form'].clearValidate()
-      })
+      this.applyPermission()
       this.dialogVisible = true
+      this.$nextTick(() => {
+        this.$refs['form'] && this.$refs['form'].clearValidate()
+      })
+    },
+    // 闈炲綋鍓嶇幆鑺傝矗浠讳汉鍙厑璁告煡鐪�
+    applyPermission() {
+      if (this.currentStep === 4) {
+        this.canOperate = false
+        return
+      }
+      const responsible = this.form.currentResponsible
+      this.canOperate = !responsible || responsible === this.nickName
+      if (!this.canOperate) {
+        this.$message.warning('褰撳墠鐜妭璐d换浜轰负锛�' + responsible + '锛屾偍鍙兘鏌ョ湅')
+      }
     },
     // 瀵煎嚭
     handleDownOne(row) {
       this.outLoading = true
       exportDeviceStatus({ deviceId: row.deviceId, processNumber: row.processNumber }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '璁惧鍋�/鍚敤.doc')
+        saveBlobOrShowError(res, '璁惧鍋�/鍚敤.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     // 鍒犻櫎
@@ -454,9 +498,8 @@
         processNumber: this.search.processNumber
       }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '璁惧鍋滅敤/鍚敤.xlsx')
-      }).finally(() => {
+        saveBlobOrShowError(res, '璁惧鍋滅敤/鍚敤.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+      }).catch(() => {
         this.outLoading = false
       })
     },
@@ -482,8 +525,6 @@
     // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
     clickNodeVal(newVal) {
       if (newVal.value) {
-        this.componentData.entity.deviceId = this.clickNodeVal.value
-        this.entityCopy = this.HaveJson(this.componentData.entity)
         this.getDeviceStatePage(newVal.value)
       }
     },
@@ -494,7 +535,7 @@
         this.closeLoading()
         this.currentStep = 0 // 姝ラ鏉℃樉绀虹鍑犳
         this.currentStepClick = 0 // 鐐瑰嚮姝ラ鏉″彉鍖�
-        this.$refs['form'].clearValidate()
+        this.$refs['form'] && this.$refs['form'].clearValidate()
       }
     }
   },
diff --git a/src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue b/src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue
index bcd8062..daac854 100644
--- a/src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue
+++ b/src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue
@@ -10,7 +10,7 @@
                   :page="page" :tableLoading="tableLoading"></lims-table>
     </div>
     <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="usageTableDia"
-               title="璁惧淇濆吇璁″垝琛�" width="80%" @close="closeDialog">
+               title="璁惧浣跨敤鎺堟潈琛�" width="80%" @close="closeDialog">
       <div style="display: flex;align-items: center;">
         <el-button size="small" type="primary" @click="addTableRow" v-if="operationType !== 'check'">娣诲姞</el-button>
         <span style="width: 60px;margin-left: 10px">骞翠唤锛�</span>
@@ -53,7 +53,7 @@
                          clearable filterable multiple
                          :disabled="operationType === 'check'"
                          placeholder="璇烽�夋嫨" size="small" style="width: 100%;">
-                <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id">
+                <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.name">
                 </el-option>
               </el-select>
             </template>
@@ -122,6 +122,8 @@
 } from "@/api/cnas/resourceDemand/device";
 import {selectUserCondition} from "@/api/system/user";
 import {mapGetters} from "@/utils/store-compat";
+import {formatListDate} from './dateFormat'
+import {saveBlobOrShowError} from '@/utils/saveBlob'
 
 export default {
   name: '',
@@ -148,9 +150,9 @@
       column: [
         { label: '璁″垝骞翠唤', prop: 'impowerYear' },
         { label: '缂栧埗浜�', prop: 'compiler' },
-        { label: '缂栧埗鏃堕棿', prop: 'datePreparation' },
+        { label: '缂栧埗鏃堕棿', prop: 'datePreparation', formatData: val => formatListDate(val) },
         { label: '鎺堟潈浜�', prop: 'audit' },
-        { label: '鎺堟潈鏃ユ湡', prop: 'auditDate' },
+        { label: '鎺堟潈鏃ユ湡', prop: 'auditDate', formatData: val => formatListDate(val) },
         {
           dataType: 'tag',
           label: '鎺堟潈鐘舵��',
@@ -205,7 +207,7 @@
                 this.openDia('check', row);
               },
               disabled: (row) => {
-                return row.status === 1 || this.userId !== row.auditId;
+                return row.status === 1 || this.userId != row.auditId;
               },
             },
             {
@@ -259,6 +261,7 @@
     },
     // 鍒嗛〉鍒囨崲
     pagination(page) {
+      this.page.current = page.page
       this.page.size = page.limit
       this.getTableList()
     },
@@ -319,9 +322,9 @@
         getImpowerDetail({ impowerId: this.impowerId }).then(res => {
           if (res.code === 200) {
             this.form = res.data
-            this.deviceImpowerDetails = this.form.deviceImpowerDetails
+            this.deviceImpowerDetails = this.form.deviceImpowerDetails || []
             this.deviceImpowerDetails.forEach(item => {
-              item['delegatedUserArr'] = item.delegatedUser.split(',')
+              item['delegatedUserArr'] = item.delegatedUser ? String(item.delegatedUser).split(',') : []
             })
           }
         }).catch(error => {
@@ -347,9 +350,24 @@
     },
     // 鎻愪氦鏂板鍜屼慨鏀�
     submitForm() {
+      if (!this.form.impowerYear) {
+        this.$message.warning('璇烽�夋嫨骞翠唤')
+        return
+      }
+      if (!this.deviceImpowerDetails.length) {
+        this.$message.warning('璇锋坊鍔犺澶�')
+        return
+      }
+      const noDelegatee = this.deviceImpowerDetails.find(item => {
+        return !Array.isArray(item.delegatedUserArr) || item.delegatedUserArr.length === 0
+      })
+      if (noDelegatee) {
+        this.$message.warning(`璇蜂负璁惧鈥�${noDelegatee.deviceName || ''}鈥濋�夋嫨琚巿鏉冧汉`)
+        return
+      }
       this.form.deviceImpowerDetails = this.HaveJson(this.deviceImpowerDetails)
       this.form.deviceImpowerDetails.forEach((item) => {
-        item.delegatedUser = item.delegatedUserArr.join(',')
+        item.delegatedUser = Array.isArray(item.delegatedUserArr) ? item.delegatedUserArr.join(',') : ''
       })
       this.submitFormLoading = true
       if (this.operationType === 'add') {
@@ -421,10 +439,12 @@
       })
     },
     openHandleOut (row) {
+      this.outLoading = true
       exportDeviceImpower({ impowerId: row.impowerId }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/msword' });
-        this.$download.saveAs(blob, '璁惧浣跨敤鎺堟潈琛�' + '.docx')
+        saveBlobOrShowError(res, '璁惧浣跨敤鎺堟潈琛�.docx', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     handleDeleteClick(row) {
diff --git a/src/views/CNAS/resourceDemand/device/component/usingExternalInstruments.vue b/src/views/CNAS/resourceDemand/device/component/usingExternalInstruments.vue
index 0cb0635..f104008 100644
--- a/src/views/CNAS/resourceDemand/device/component/usingExternalInstruments.vue
+++ b/src/views/CNAS/resourceDemand/device/component/usingExternalInstruments.vue
@@ -36,15 +36,15 @@
           <!-- 鎿嶄綔鎸夐挳 -->
           <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="150">
             <template #default="scope">
-              <el-button :disabled="scope.row.ratifyStatus === 1" size="small" link type="primary"
+              <el-button :disabled="scope.row.isFinish === 1" size="small" link type="primary"
                 @click="handleForm(scope.row.externalApplyId)">鎿嶄綔</el-button>
               <el-button size="small" link type="primary" @click="handleDownOne(scope.row.externalApplyId)">瀵煎嚭</el-button>
-              <el-button size="small" link type="danger"
+              <el-button :disabled="scope.row.isFinish === 1" size="small" link type="danger"
                 @click="deleteFun(scope.row.externalApplyId)">鍒犻櫎</el-button>
             </template>
           </el-table-column>
         </el-table>
-        <el-pagination :current-page="1" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
+        <el-pagination :current-page="pagination1.current" :page-size="pagination1.size" :page-sizes="[10, 20, 30, 50, 100]"
           :total="pagination1.total" layout="->,total, sizes, prev, pager, next, jumper" background
           @size-change="handleSizeChange1" @current-change="handleCurrentChange1">
         </el-pagination>
@@ -61,6 +61,7 @@
   exportDeviceExternalApply,
   delDeviceExternalApply,
 } from '@/api/cnas/resourceDemand/device.js'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
 export default {
   name: "using-external-instruments",
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
@@ -135,8 +136,9 @@
       this.outLoading = true
       exportDeviceExternalApply({ externalApplyId: id }).then(res => {
         this.outLoading = false
-        const blob = new Blob([res], { type: 'application/octet-stream' });
-        this.$download.saveAs(blob, '鍒╃敤澶栭儴浠櫒璁惧鐢宠琛�.doc')
+        saveBlobOrShowError(res, '鍒╃敤澶栭儴浠櫒璁惧鐢宠琛�.doc', 'application/msword')
+      }).catch(() => {
+        this.outLoading = false
       })
     },
     // 鍒犻櫎
diff --git a/src/views/CNAS/resourceDemand/device/index.vue b/src/views/CNAS/resourceDemand/device/index.vue
index 4bbf1e4..fe4cbfd 100644
--- a/src/views/CNAS/resourceDemand/device/index.vue
+++ b/src/views/CNAS/resourceDemand/device/index.vue
@@ -39,7 +39,8 @@
             <overview v-if="menuListActiveName == '璁惧鎬昏'" :clickNodeVal="clickNodeVal" @refresh-tree="geList" />
           </el-tab-pane>
           <el-tab-pane label="璁惧宸ュ叿鏄庣粏" name="璁惧宸ュ叿鏄庣粏">
-            <management v-if="menuListActiveName == '璁惧宸ュ叿鏄庣粏'" :clickNodeVal="clickNodeVal" />
+            <management v-if="menuListActiveName == '璁惧宸ュ叿鏄庣粏'" :clickNodeVal="clickNodeVal"
+              @refresh-tree="geList" />
           </el-tab-pane>
           <el-tab-pane label="璁惧鏍″噯璁″垝" name="璁惧鏍″噯璁″垝">
             <equipment-calibration-plan v-if="menuListActiveName == '璁惧鏍″噯璁″垝'"
@@ -68,7 +69,8 @@
       <div v-if="!isShowAll" style="height: 100%;">
         <el-tabs v-model="tabListActiveName" class="main_right" type="border-card" @tab-click="handleClick">
           <el-tab-pane label="璁惧妗f" name="璁惧妗f">
-            <files v-if="tabListActiveName == '璁惧妗f'" :clickNodeVal="clickNodeVal" />
+            <files v-if="tabListActiveName == '璁惧妗f'" :clickNodeVal="clickNodeVal"
+              @refresh-tree="geList" />
           </el-tab-pane>
           <el-tab-pane label="璁惧楠屾敹" name="璁惧楠屾敹">
             <equipment-acceptance v-if="tabListActiveName == '璁惧楠屾敹'" :clickNodeVal="clickNodeVal"></equipment-acceptance>
@@ -136,6 +138,7 @@
 import {
   treeDevice,
 } from '@/api/cnas/resourceDemand/device.js'
+import dayjs from 'dayjs'
 export default {
   name: 'Device',
   components: {
@@ -205,13 +208,10 @@
     // 鍒ゆ柇鏄惁闇�瑕佹爣绾�
     shouldHighlight(data) {
       if (!data.activationDate) return false;
-      const today = new Date();
-      const targetDate = new Date(data.activationDate);
-      const fiveDaysBeforeTarget = new Date(targetDate);
-      // 璁$畻鍓嶄簲澶╃殑鏃ユ湡
-      fiveDaysBeforeTarget.setDate(targetDate.getDate() - 5);
-
-      return today > fiveDaysBeforeTarget;
+      const targetDate = dayjs(data.activationDate);
+      if (!targetDate.isValid()) return false;
+      // 鏍″噯鏈夋晥鏈熷墠 1 涓湀寮�濮嬫爣绾�
+      return dayjs().isAfter(targetDate.subtract(1, 'month'));
     },
     handleNodeClick(val, node, el) {
       // 鐐瑰嚮涓存椂缂撳瓨
diff --git a/src/views/CNAS/resourceDemand/facilitiesEnvironment/component/facilities-environmental-conditions.vue b/src/views/CNAS/resourceDemand/facilitiesEnvironment/component/facilities-environmental-conditions.vue
index cca75f6..753fc33 100644
--- a/src/views/CNAS/resourceDemand/facilitiesEnvironment/component/facilities-environmental-conditions.vue
+++ b/src/views/CNAS/resourceDemand/facilitiesEnvironment/component/facilities-environmental-conditions.vue
@@ -2,44 +2,26 @@
   <el-row>
     <el-col :span="2">
       <el-menu @select="clickSelect" :default-active="activeName">
-        <el-menu-item index="鐢垫簮绋冲畾鎬�">
-          <span>鐢垫簮绋冲畾鎬�</span>
-        </el-menu-item>
-        <el-menu-item index="闃查浄妫�娴�">
-          <span>闃查浄妫�娴�</span>
-        </el-menu-item>
-        <el-menu-item index="鐓у害璁板綍">
-          <span>鐓у害璁板綍</span>
-        </el-menu-item>
         <el-menu-item index="娓╂箍搴﹁褰�">
           <span>娓╂箍搴﹁褰�</span>
         </el-menu-item>
       </el-menu>
     </el-col>
     <el-col :span="22" style="padding: 10px">
-      <power-supply-stability v-if="activeName === '鐢垫簮绋冲畾鎬�'"/>
-      <lightning-protection-detection v-if="activeName === '闃查浄妫�娴�'" />
-      <illuminance-recording v-if="activeName === '鐓у害璁板綍'"/>
       <temperature-humidity-record v-if="activeName === '娓╂箍搴﹁褰�'"/>
     </el-col>
   </el-row>
 </template>
 
 <script>
-// 鐢垫簮绋冲畾鎬�
-import PowerSupplyStability from "./facilities-environmental-conditions/power-supply-stability.vue";
-// 闃查浄妫�娴�
-import LightningProtectionDetection from "./facilities-environmental-conditions/lightning-protection-detection.vue";
-// 鐓у害璁板綍
-import IlluminanceRecording from "./facilities-environmental-conditions/illuminance-recording.vue";
 // 娓╂箍搴﹁褰�
 import TemperatureHumidityRecord from "./facilities-environmental-conditions/temperature-humidity-record.vue";
 
 export default {
-  components: {TemperatureHumidityRecord, IlluminanceRecording, LightningProtectionDetection, PowerSupplyStability},
+  components: {TemperatureHumidityRecord},
   data() {
     return {
-      activeName: "鐢垫簮绋冲畾鎬�"
+      activeName: "娓╂箍搴﹁褰�"
     }
   },
   methods: {
diff --git a/src/views/CNAS/resourceDemand/standardMaterial/index.vue b/src/views/CNAS/resourceDemand/standardMaterial/index.vue
index faee58c..39c9343 100644
--- a/src/views/CNAS/resourceDemand/standardMaterial/index.vue
+++ b/src/views/CNAS/resourceDemand/standardMaterial/index.vue
@@ -109,9 +109,14 @@
           minWidth: '100'
         },
         {
-          label: '鏁伴噺',
+          label: '鍘熷鏁伴噺',
           prop: 'quantity',
           minWidth: '100'
+        },
+        {
+          label: '浣欓噺',
+          prop: 'remainingQuantity',
+          minWidth: '80'
         },
         {
           label: '鍗曚綅',
@@ -167,6 +172,9 @@
               clickFun: (row) => {
                 this.borrow(row);
               },
+              disabled: (row) => {
+                return Number(row.remainingQuantity) <= 0;
+              },
             },
             {
               name: '鍒犻櫎',

--
Gitblit v1.9.3