From 137bf2c0666b60cfc0d98b1a9ca7ead860ee4e7c Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期三, 28 十月 2026 17:57:29 +0800
Subject: [PATCH] feat(device,supply,satisfaction): 设备计划改造、耗材采购调整与满意度照片上传

---
 src/views/CNAS/externalService/serviceAndSupplyPro/component/Edit.vue          |  294 ++++++-----
 src/views/CNAS/systemManagement/customerSatisfaction/components/formDialog.vue |   49 +
 src/api/cnas/resourceDemand/device.js                                          |   25 +
 src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue        |  393 +++++++---------
 src/views/CNAS/externalService/serviceAndSupplyPro/component/Store.vue         |    8 
 src/components/Attachment/lims-attachment.vue                                  |   37 +
 src/views/CNAS/externalService/serviceAndSupplyPro/index.vue                   |   36 -
 src/views/CNAS/resourceDemand/device/component/checkRecord.vue                 |   32 
 src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue          |    2 
 src/components/Preview/filePreview.vue                                         |    8 
 src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue   |   66 +-
 src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue    |  372 ++++++++++++----
 12 files changed, 771 insertions(+), 551 deletions(-)

diff --git a/src/api/cnas/resourceDemand/device.js b/src/api/cnas/resourceDemand/device.js
index ada69dc..ba8327e 100644
--- a/src/api/cnas/resourceDemand/device.js
+++ b/src/api/cnas/resourceDemand/device.js
@@ -332,6 +332,14 @@
     params: query,
   });
 }
+//璁惧鏍告煡璁″垝 骞翠唤鍒楄〃锛堟病鏈夋槑缁嗙殑绌哄勾浠借嚜鍔ㄥ垹闄わ級
+export function getExaminePlanYears(query) {
+  return request({
+    url: "/deviceExaminePlan/getPlanYears",
+    method: "get",
+    params: query,
+  });
+}
 
 // 璁惧鏍告煡璁″垝鎻愪氦鎵瑰噯閫氱煡
 export function submitRatifyDeviceExaminePlan(data) {
@@ -557,6 +565,14 @@
 export function getMaintenancePlanByYear(query) {
   return request({
     url: "/deviceMaintenancePlan/getPlanByYear",
+    method: "get",
+    params: query,
+  });
+}
+//璁惧淇濆吇璁″垝 骞翠唤鍒楄〃锛堟病鏈夋槑缁嗙殑绌哄勾浠借嚜鍔ㄥ垹闄わ級
+export function getMaintenancePlanYears(query) {
+  return request({
+    url: "/deviceMaintenancePlan/getPlanYears",
     method: "get",
     params: query,
   });
@@ -1334,7 +1350,14 @@
     data: query,
   });
 }
-
+//淇濆吇璁板綍 瀹℃牳
+export function reviewDeviceMaintenance(data) {
+  return request({
+    url: "/deviceMaintain/reviewDeviceMaintenance",
+    method: "post",
+    data: data,
+  });
+}
 //浣跨敤璁板綍 瀵煎嚭
 export function exportDeviceMaintenance(query) {
   return request({
diff --git a/src/components/Attachment/lims-attachment.vue b/src/components/Attachment/lims-attachment.vue
index ae6a8b0..78fc148 100644
--- a/src/components/Attachment/lims-attachment.vue
+++ b/src/components/Attachment/lims-attachment.vue
@@ -5,7 +5,7 @@
         <div class="el-upload__tip">
           {{ readonly ? '浠呭彲棰勮銆佷笅杞介檮浠�' : ((currentId || deferUpload) ? tip : emptyTip) }}
         </div>
-        <el-upload v-if="!readonly" :action="uploadAction" :headers="uploadHeader" multiple
+        <el-upload v-if="!readonly" :action="uploadAction" :headers="uploadHeader" multiple :accept="accept"
           :show-file-list="false" :disabled="!canUpload" :auto-upload="!deferUpload"
           :on-change="handleFileChange" :on-success="handleUploadSuccess"
           :on-error="handleUploadError">
@@ -18,6 +18,7 @@
         <el-table-column label="鎿嶄綔" width="170">
           <template #default="scope">
             <template v-if="scope.row.pending">
+              <el-button link type="primary" @click="previewPending(scope.row)">棰勮</el-button>
               <el-button link type="danger" @click="removePending(scope.row)">鍒犻櫎</el-button>
             </template>
             <template v-else>
@@ -32,7 +33,7 @@
     <el-dialog v-else :title="dialogTitle" v-model="visible" width="760px" append-to-body @close="$emit('closed')">
       <div class="attachment-header">
         <div class="el-upload__tip">{{ readonly ? '浠呭彲棰勮銆佷笅杞介檮浠�' : tip }}</div>
-        <el-upload v-if="!readonly" :action="uploadAction" :headers="uploadHeader" multiple
+        <el-upload v-if="!readonly" :action="uploadAction" :headers="uploadHeader" multiple :accept="accept"
           :show-file-list="false" :on-success="handleUploadSuccess" :on-error="handleUploadError">
           <el-button size="small" type="primary">涓婁紶闄勪欢</el-button>
         </el-upload>
@@ -52,7 +53,7 @@
         <el-button @click="visible = false">鍏� 闂�</el-button>
       </template>
     </el-dialog>
-    <el-dialog title="棰勮闄勪欢" v-model="previewVisible" fullscreen append-to-body>
+    <el-dialog title="棰勮闄勪欢" v-model="previewVisible" fullscreen append-to-body @close="releasePreviewBlob">
       <file-preview v-if="previewVisible" :file-url="previewUrl" :current-file="previewRow" />
     </el-dialog>
   </div>
@@ -147,6 +148,11 @@
     deferUpload: {
       type: Boolean,
       default: false
+    },
+    // 鍏佽閫夋嫨鐨勬枃浠剁被鍨嬶紝濡� .jpg,.png锛涗负绌轰笉闄愬埗
+    accept: {
+      type: String,
+      default: ''
     }
   },
   watch: {
@@ -173,7 +179,8 @@
       currentRow: {},
       previewVisible: false,
       previewRow: {},
-      previewUrl: ''
+      previewUrl: '',
+      previewBlobUrl: ''
     }
   },
   computed: {
@@ -201,6 +208,9 @@
     uploadAction() {
       return this.javaApi + this.uploadUrl + '?' + this.idParam + '=' + this.currentId
     }
+  },
+  beforeUnmount() {
+    this.releasePreviewBlob()
   },
   methods: {
     // 鎵撳紑闄勪欢绠$悊寮圭獥
@@ -293,7 +303,26 @@
         this.loadList()
       })
     },
+    // 寰呬笂浼犳枃浠剁敤鏈湴涓存椂鍦板潃棰勮锛屾彁浜ゅ悗鍐嶈蛋姝e紡鍦板潃
+    previewPending(row) {
+      const item = this.pendingFiles.find(pending => pending.uid === row.uid)
+      if (!item) {
+        return
+      }
+      this.releasePreviewBlob()
+      this.previewBlobUrl = URL.createObjectURL(item.raw)
+      this.previewRow = { fileName: item.fileName, fileUrl: this.previewBlobUrl }
+      this.previewUrl = this.previewBlobUrl
+      this.previewVisible = true
+    },
+    releasePreviewBlob() {
+      if (this.previewBlobUrl) {
+        URL.revokeObjectURL(this.previewBlobUrl)
+        this.previewBlobUrl = ''
+      }
+    },
     previewFile(row) {
+      this.releasePreviewBlob()
       this.previewRow = row
       this.previewUrl = this.fullUrl(row.fileUrl)
       this.previewVisible = true
diff --git a/src/components/Preview/filePreview.vue b/src/components/Preview/filePreview.vue
index e8ec772..69d3b3d 100644
--- a/src/components/Preview/filePreview.vue
+++ b/src/components/Preview/filePreview.vue
@@ -110,8 +110,12 @@
     }
   },
   computed: {
+    // blob 涓存椂鍦板潃鏈韩涓嶅甫鎵╁睍鍚嶏紝寰呬笂浼犳枃浠堕潬鍘熷鏂囦欢鍚嶅垽鏂被鍨�
+    currentFileName() {
+      return (this.currentFile && this.currentFile.fileName) || ''
+    },
     isImage() {
-      return /\.(jpg|jpeg|png|gif)$/i.test(this.fileUrl)
+      return /\.(jpg|jpeg|png|gif)$/i.test(this.fileUrl) || /\.(jpg|jpeg|png|gif)$/i.test(this.currentFileName)
     },
     imgUrl() {
       // 鍥剧墖瀛樺湪 /img 闈欐�佽矾寰勪笅锛岃皟鐢ㄦ柟浼犵殑鍙兘鏄� /word 鍦板潃锛岃繖閲岀粺涓�鎹㈡垚 /img
@@ -155,7 +159,7 @@
       }
     },
     fileExt() {
-      const match = this.fileUrl.match(/\.([a-zA-Z0-9]+)$/)
+      const match = (this.currentFileName || this.fileUrl).match(/\.([a-zA-Z0-9]+)$/)
       return match ? match[1].toUpperCase() : '鏈煡'
     },
     // 璋冪敤鏂逛紶浜� OnlyOffice 鐨勯厤缃墠璧版枃妗f湇鍔★紝鍚﹀垯鐢ㄦ祻瑙堝櫒鍐呯疆闃呰鍣�
diff --git a/src/views/CNAS/externalService/serviceAndSupplyPro/component/Edit.vue b/src/views/CNAS/externalService/serviceAndSupplyPro/component/Edit.vue
index c569e8b..e83fb8c 100644
--- a/src/views/CNAS/externalService/serviceAndSupplyPro/component/Edit.vue
+++ b/src/views/CNAS/externalService/serviceAndSupplyPro/component/Edit.vue
@@ -1,127 +1,125 @@
 <template>
   <el-dialog
     v-model="dialogVisible"
-    title="娣诲姞鑰楁潗椤圭洰淇℃伅"
-    width="70%"
+    :title="model.id ? '缂栬緫鑰楁潗' : '鏂板鑰楁潗'"
+    width="1100px"
   >
     <el-form ref="modelForm" :model="model" :rules="rules" label-width="100px">
-      <el-col :span="12">
-        <el-form-item label="鑰楁潗绫诲瀷" prop="consumablesType">
-          <el-select v-model="model.consumablesType" placeholder="璇烽�夋嫨鑰楁潗绫诲瀷" size="small" style="width: 100%">
-            <el-option v-for="(v, i) in dict.type.consumables_type" :key="i" :label="v.label" :value="v.value"></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="璐у彿">
-          <el-input v-model="model.itemNumber" placeholder="璇疯緭鍏ヨ揣鍙�" size="small"></el-input>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="鑰楁潗鍚嶇О">
-          <el-input v-model="model.consumablesName" placeholder="璇疯緭鍏ヨ�楁潗鍚嶇О" size="small"></el-input>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="瑙勬牸">
-          <el-input v-model="model.specifications" placeholder="璇疯緭鍏ヨ鏍�" size="small"></el-input>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="璁¢噺鍗曚綅">
-          <el-input v-model="model.unit" placeholder="璇疯緭鍏ヨ閲忓崟浣�" size="small"></el-input>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="鍙傝�冧环鏍�">
-          <el-input-number v-model="model.referencePrice" :min="0" :precision="2" :step="0.01" placeholder="璇疯緭鍏ュ弬鑰冧环鏍�"
-                           size="small"></el-input-number>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="瀛樻斁浣嶇疆">
-          <el-select v-model="model.contentId" placeholder="璇烽�夋嫨瀛樻斁浣嶇疆" size="small" style="width: 100%">
-            <el-option v-for="(v, i) in procurementSuppliesContentOptions" :key="i" :label="v.nodeName"
-                       :value="v.id"></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="璐熻矗浜�">
-          <el-select v-model="model.personInCharge" placeholder="璇烽�夋嫨璐熻矗浜�" size="small" style="width: 100%">
-            <el-option v-for="(v, i) in userOptions" :key="i" :label="v.name" :value="v.id"></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="搴撳瓨涓婇檺">
-          <el-input-number v-model="model.upperLimit" :min="0" :step="1" placeholder="璇疯緭鍏ュ簱瀛樹笂闄�" size="small"></el-input-number>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="搴撳瓨涓嬮檺">
-          <el-input-number v-model="model.lowerLimit" :min="0" :step="1" placeholder="璇疯緭鍏ュ簱瀛樹笅闄�" size="small"></el-input-number>
-        </el-form-item>
-      </el-col>
-      <el-col :span="24">
-        <el-form-item label="渚涘簲鍟�">
-          <el-select v-model="model.supplier" placeholder="璇烽�夋嫨渚涘簲鍟�" size="small" style="width: 100%">
-            <el-option v-for="(v, i) in supplierOptions" :key="i" :label="v.supplierName"
-                       :value="v.supplierManagementId"></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-      <el-col :span="24">
-        <el-form-item label="鑰楁潗鍥炬爣">
-          <div class="rows">
-            <el-input v-model="model.consumablesIcon" placeholder="璇疯緭鍏ヨ�楁潗鍥炬爣" size="small" style="width: 90%;"/>
-            <el-upload
-              ref="upload"
-              :action="action"
-              :headers="uploadHeader"
-              :on-success="onSuccessIcon"
-              :show-file-list="false"
-              style="float: left; margin: 0 12px 0 20px;"
-            >
-              <template #trigger><el-button  class="uploadFile" size="small" type="primary">娴忚</el-button></template>
-            </el-upload>
-          </div>
-        </el-form-item>
-      </el-col>
-      <el-col :span="24">
-        <el-form-item label="鑰楁潗闄勪欢">
-          <div class="rows">
-            <el-input v-model="model.attachment" placeholder="璇疯緭鍏ヨ�楁潗闄勪欢" size="small" style="width: 90%;"/>
-            <el-upload
-              ref="upload"
-              :action="action"
-              :on-success="onSuccessFile"
-              :show-file-list="false"
-              :headers="uploadHeader"
-              style="float: left; margin: 0 12px 0 20px;"
-            >
-              <template #trigger><el-button  class="uploadFile" size="small" type="primary">娴忚</el-button></template>
-            </el-upload>
-          </div>
-        </el-form-item>
-      </el-col>
-      <el-col :span="24">
-        <el-form-item label="澶囨敞">
-          <el-input
-            v-model="model.remark"
-            :rows="2"
-            placeholder="璇疯緭鍏ュ娉�"
-            size="small"
-            type="textarea"
-          >
-          </el-input>
-        </el-form-item>
-      </el-col>
+      <div class="section-title">鍩烘湰淇℃伅</div>
+      <el-row :gutter="24">
+        <el-col :span="12">
+          <el-form-item label="鑰楁潗绫诲瀷" prop="consumablesType">
+            <el-select v-model="model.consumablesType" placeholder="璇烽�夋嫨鑰楁潗绫诲瀷" style="width: 100%">
+              <el-option v-for="(v, i) in dict.type.consumables_type" :key="i" :label="v.label" :value="v.value"></el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="鑰楁潗鍚嶇О">
+            <el-input v-model="model.consumablesName" clearable placeholder="璇疯緭鍏ヨ�楁潗鍚嶇О"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="璐у彿">
+            <el-input v-model="model.itemNumber" clearable placeholder="璇疯緭鍏ヨ揣鍙�"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="瑙勬牸">
+            <el-input v-model="model.specifications" clearable placeholder="璇疯緭鍏ヨ鏍�"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="璁¢噺鍗曚綅">
+            <el-input v-model="model.unit" clearable placeholder="璇疯緭鍏ヨ閲忓崟浣�"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="鍙傝�冧环鏍�">
+            <el-input-number v-model="model.referencePrice" :min="0" :precision="2" :step="0.01" placeholder="璇疯緭鍏ュ弬鑰冧环鏍�"
+                             controls-position="right" style="width: 100%"></el-input-number>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="瀛樻斁浣嶇疆">
+            <el-input v-model="model.storageLocation" clearable placeholder="璇疯緭鍏ュ瓨鏀句綅缃�"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="璐熻矗浜�">
+            <el-select v-model="model.personInCharge" placeholder="璇烽�夋嫨璐熻矗浜�" style="width: 100%">
+              <el-option v-for="(v, i) in userOptions" :key="i" :label="v.name" :value="v.id"></el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <div class="section-title">搴撳瓨涓庝緵搴斿晢</div>
+      <el-row :gutter="24">
+        <el-col :span="12">
+          <el-form-item label="搴撳瓨涓婇檺">
+            <el-input-number v-model="model.upperLimit" :min="0" :step="1" placeholder="璇疯緭鍏ュ簱瀛樹笂闄�"
+                             controls-position="right" style="width: 100%"></el-input-number>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="搴撳瓨涓嬮檺">
+            <el-input-number v-model="model.lowerLimit" :min="0" :step="1" placeholder="璇疯緭鍏ュ簱瀛樹笅闄�"
+                             controls-position="right" style="width: 100%"></el-input-number>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="渚涘簲鍟�">
+            <el-select v-model="model.supplier" placeholder="璇烽�夋嫨渚涘簲鍟�" style="width: 100%">
+              <el-option v-for="(v, i) in supplierOptions" :key="i" :label="v.supplierName"
+                         :value="v.supplierManagementId"></el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <div class="section-title">鍥炬爣涓庨檮浠�</div>
+      <el-row :gutter="24">
+        <el-col :span="24">
+          <el-form-item label="鑰楁潗鍥炬爣">
+            <div class="upload-row">
+              <el-input v-model="model.consumablesIcon" clearable placeholder="涓婁紶鍚庤嚜鍔ㄥ~鍏咃紝涔熷彲鎵嬪姩濉啓"></el-input>
+              <el-upload
+                :action="action"
+                :headers="uploadHeader"
+                :on-success="onSuccessIcon"
+                :show-file-list="false"
+              >
+                <el-button :icon="$icon('el-icon-upload2')" type="primary" plain>涓婁紶</el-button>
+              </el-upload>
+            </div>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="鑰楁潗闄勪欢">
+            <div class="upload-row">
+              <el-input v-model="model.attachment" clearable placeholder="涓婁紶鍚庤嚜鍔ㄥ~鍏咃紝涔熷彲鎵嬪姩濉啓"></el-input>
+              <el-upload
+                :action="action"
+                :headers="uploadHeader"
+                :on-success="onSuccessFile"
+                :show-file-list="false"
+              >
+                <el-button :icon="$icon('el-icon-upload2')" type="primary" plain>涓婁紶</el-button>
+              </el-upload>
+            </div>
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-form-item class="remark-item" label-width="0">
+        <el-input v-model="model.remark" :rows="4" placeholder="璇疯緭鍏ュ娉�" type="textarea"></el-input>
+      </el-form-item>
     </el-form>
-    <template #footer><span  class="dialog-footer">
-            <el-button @click="resetForm">鍙� 娑�</el-button>
-            <el-button type="primary" @click="submit">淇� 瀛�</el-button>
-        </span></template>
+    <template #footer><span class="dialog-footer">
+      <el-button @click="resetForm">鍙� 娑�</el-button>
+      <el-button type="primary" @click="submit">淇� 瀛�</el-button>
+    </span></template>
   </el-dialog>
 </template>
 
@@ -130,7 +128,6 @@
   addProcurementSuppliesList,
   updateProcurementSuppliesList,
   selectSupplierManagementAll,
-  getProcurementSuppliesContentsNodeNames,
   selectUserCondition
 } from '@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro'
 export default {
@@ -142,7 +139,6 @@
         consumablesIcon: undefined,
         attachment: undefined,
       },
-      procurementSuppliesContentOptions: [],
       userOptions: [],
       supplierOptions: [],
       rules: {
@@ -163,7 +159,6 @@
     }
   },
   mounted() {
-    this.findProcurementSuppliesContentOptions()
     this.findUserOptions()
     this.findSupplierOptions()
   },
@@ -178,16 +173,10 @@
         console.log("row", row)
         this.model = row
       } else {
-        this.model = {}
+        // 鏂板鏃舵寕鍦ㄥ綋鍓嶅乏鏍戦�変腑鐨勭洰褰曡妭鐐逛笅锛屽瓨鏀句綅缃敼涓烘墜鍔ㄥ~鍐�
+        this.model = { contentId: this.contentsId }
       }
       this.dialogVisible = true
-    },
-    findProcurementSuppliesContentOptions() {
-      getProcurementSuppliesContentsNodeNames().then(res => {
-        if (res.code === 200) {
-          this.procurementSuppliesContentOptions = res.data
-        }
-      })
     },
     findUserOptions() {
       selectUserCondition().then(res => {
@@ -212,6 +201,11 @@
     submit() {
       this.$refs.modelForm.validate((valid) => {
         if (valid) {
+          // 鏂板鐨勮�楁潗鎸傚湪宸︿晶閫変腑鐨勭洰褰曡妭鐐逛笅锛屾湭閫夎妭鐐逛細淇濆瓨鎴愬垪琛ㄩ噷鐪嬩笉鍒扮殑鏁版嵁
+          if (!this.model.id && !this.contentsId) {
+            this.$message.warning('璇峰厛鍦ㄥ乏渚ч�夋嫨鑰楁潗鐩綍鑺傜偣')
+            return
+          }
           if (this.model.id) {
             updateProcurementSuppliesList(this.model).then(res => {
               if (res.code === 200) {
@@ -238,15 +232,45 @@
   margin: 6vh auto 50px !important;
 }
 :deep(.el-dialog__body) {
-  max-height: 42em;
+  max-height: 70vh;
   overflow-y: auto;
+  padding: 24px 32px;
 }
-.rows {
-  width: 100%;
+.section-title {
   display: flex;
-  justify-content: space-between;
+  align-items: center;
+  font-size: 15px;
+  font-weight: 600;
+  color: var(--lims-text);
+  padding-bottom: 10px;
+  border-bottom: 1px solid var(--lims-divider);
+  margin: 8px 0 20px;
 }
-:deep(.el-form-item__content) {
-  line-height: 39px;
+.section-title:not(:first-child) {
+  margin-top: 28px;
+}
+.section-title::before {
+  content: '';
+  display: inline-block;
+  width: 3px;
+  height: 15px;
+  border-radius: 2px;
+  background: var(--el-color-primary);
+  margin-right: 8px;
+}
+.upload-row {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  width: 100%;
+}
+.upload-row .el-input {
+  flex: 1;
+}
+:deep(.el-form-item) {
+  margin-bottom: 20px;
+}
+.remark-item {
+  margin-top: 28px;
 }
 </style>
diff --git a/src/views/CNAS/externalService/serviceAndSupplyPro/component/Store.vue b/src/views/CNAS/externalService/serviceAndSupplyPro/component/Store.vue
index 37a324f..b2b5498 100644
--- a/src/views/CNAS/externalService/serviceAndSupplyPro/component/Store.vue
+++ b/src/views/CNAS/externalService/serviceAndSupplyPro/component/Store.vue
@@ -63,7 +63,8 @@
           <div>
             <div>
               <span>鑰楁潗鍚嶇О:</span>
-              <el-select v-model="formTwo.id" filterable placeholder="璇烽�夋嫨鑰楁潗鍚嶇О" size="small" style="width: 70%">
+              <el-select v-model="formTwo.id" filterable placeholder="璇烽�夋嫨鑰楁潗鍚嶇О" size="small" style="width: 70%"
+                @change="handleConsumableChange">
                 <el-option v-for="(v, i) in consumableOptions" :key="i" :label="v.consumablesName"
                   :value="v.id"></el-option>
               </el-select>
@@ -296,6 +297,11 @@
       console.log(val)
       return this.options.find(item => item.value === val).label
     },
+    // 閫夋嫨鑰楁潗鍚嶇О鍚庯紝鍗曚环鑷姩甯﹀嚭鑰楁潗鍒楄〃閲岀殑鍙傝�冧环鏍硷紙浠嶅彲鎵嬪姩淇敼锛�
+    handleConsumableChange(id) {
+      const item = this.consumableOptions.find(v => v.id === id)
+      this.formTwo.unitPrice = item && item.referencePrice != null ? item.referencePrice : null
+    },
     // 娣诲姞琛ㄦ牸鏁版嵁
     addTableData() {
       this.$nextTick()
diff --git a/src/views/CNAS/externalService/serviceAndSupplyPro/index.vue b/src/views/CNAS/externalService/serviceAndSupplyPro/index.vue
index 048b46a..74255ed 100644
--- a/src/views/CNAS/externalService/serviceAndSupplyPro/index.vue
+++ b/src/views/CNAS/externalService/serviceAndSupplyPro/index.vue
@@ -33,21 +33,11 @@
         <el-tab-pane label="鑰楁潗鍏ュ簱" name="third" :lazy="true">
           <Store v-if="activeName == 'third'" :contentsId="contentsId"></Store>
         </el-tab-pane>
-        <el-tab-pane label="鐩綍缁存姢" name="fourth" :lazy="true">
-          <Contents
-            v-if="activeName == 'fourth'"
-            :id="contentsId"
-            @contentsUpdate="contentsUpdate"
-            :treeData="treeData"
-            from="鑰楁潗鏍�"
-          ></Contents>
-        </el-tab-pane>
       </el-tabs>
     </div>
   </div>
 </template>
 <script>
-import Contents from "./component/contents.vue";
 import Store from "./component/Store.vue";
 import ConsumableOverview from "./component/ConsumableOverview.vue";
 import ConsumableList from "./component/ConsumableList.vue"
@@ -74,7 +64,6 @@
     };
   },
   components: {
-    Contents,
     Store,
     ConsumableOverview,
     ConsumableList
@@ -106,31 +95,6 @@
       findNodesWithFiber(this.treeData);
     },
 
-    // 鐩綍缁存姢鏇存柊
-    contentsUpdate(val, flag = false) {
-      if (val) {
-        this.getTreeData();
-        this.expandedKeys = [];
-        if (flag) {
-          const findNodesWithFiber = (nodes) => {
-            nodes.forEach((item) => {
-              if (item.parentId == val) {
-                this.expandedKeys.push(item.id);
-              }
-              if(item.children && item.children.length > 0) {
-                findNodesWithFiber(item.children);
-              }
-            });
-          };
-          findNodesWithFiber(this.treeData);
-          this.expandedKeys = this.expandedKeys.filter((item) => item !== val);
-        } else {
-          this.expandedKeys.push(val);
-        }
-      }else {
-        this.getTreeData();
-      }
-    },
     // 鏌ヨ鎵�鏈夌洰褰�
     getTreeData() {
       directoryListing().then((res) => {
diff --git a/src/views/CNAS/resourceDemand/device/component/checkRecord.vue b/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
index bbd9d3c..0c50e49 100644
--- a/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
+++ b/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
@@ -349,23 +349,16 @@
         return
       }
       const isMonthOnly = /^\d{4}-\d{2}$/.test(checkTime)
-      const nowYear = nowMonth.slice(0, 4)
       const todayStr = `${nowMonth}-${String(now.getDate()).padStart(2, '0')}`
       const plannedText = isMonthOnly
-        ? (this.planDueDate ? `${this.planDueDate}锛堣鍒掓湀浠� ${checkTime}锛塦 : `${checkTime}锛堢郴缁熻鍒掑彧鐧昏鍒版湀浠斤級`)
+        ? (this.planDueDate ? `${this.planDueDate}锛堣鍒掓湀浠� ${checkTime}锛塦 : `${checkTime}锛堢郴缁熺櫥璁板彧鍒版湀浠斤級`)
         : checkTime
-      const head = `<div class="er-head">璇ユ潯璁板綍鐨勮鍒掓牳鏌ユ椂闂翠负 <b>${plannedText}</b>锛屽綋鍓嶅鏍告棩鏈熸槸 <b>${todayStr}</b>锛屽睘浜�<b>鎻愬墠瀹℃牳</b>銆�</div>`
-      const items = isMonthOnly
-        ? [
-          `鏈疆璁板綍鎸夊疄闄呭鏍告湀浠藉綊妗o細鏍告煡鏃堕棿鐧昏涓� <b>${nowMonth}</b>锛堝疄闄呭鏍告棩鏈� ${todayStr}锛夛紝骞跺綊鍏� <b>${nowYear} 骞磋澶囨牳鏌ヨ鍒�</b>锛堝垏鍒� ${nowYear} 骞村彲鐪嬪埌锛岀姸鎬佹樉绀衡�滈�氳繃鈥濓級銆俙,
-          `绯荤粺浼氭寜璁惧鐨勬牳鏌ュ懆鏈熻嚜鍔ㄧ敓鎴愪笅涓�杞緟鏍告煡浠诲姟锛堝湪涓嬫鏍告煡鏃ユ湡鎵�灞炲勾浠界殑璁″垝涓級锛屽垵濮嬬姸鎬佲�滄湭寮�濮嬧�濃�斺�旇繖鏄甯哥幇璞★紝涓嶆槸瀹℃牳娌$敓鏁堛�俙,
-          `璁惧妗f鐨勬渶杩戞牳鏌ユ棩鏈熸洿鏂颁负 <b>${todayStr}</b>锛屼笅娆℃牳鏌ユ棩鏈熸寜鏍告煡鍛ㄦ湡鑷姩璁$畻銆俙
-        ]
-        : [
-          `璇ヨ褰曚繚鐣欏師鏍告煡鏃ユ湡 <b>${checkTime}</b>锛屽鏍哥姸鎬佹樉绀衡�滈�氳繃鈥濄�俙,
-          `绯荤粺浼氭寜璁惧鐨勬牳鏌ュ懆鏈熻嚜鍔ㄧ敓鎴愪笅涓�杞緟鏍告煡浠诲姟锛堝湪涓嬫鏍告煡鏃ユ湡鎵�灞炲勾浠界殑璁″垝涓級锛屽垵濮嬬姸鎬佲�滄湭寮�濮嬧�濓紝杩欐槸姝e父鐜拌薄銆俙,
-          `璁惧妗f鐨勬渶杩戞牳鏌ユ棩鏈熸洿鏂颁负 <b>${todayStr}</b>锛屼笅娆℃牳鏌ユ棩鏈熸寜鏍告煡鍛ㄦ湡鑷姩璁$畻銆俙
-        ]
+      const head = `<div class="er-head">璇ユ潯璁板綍鐨勮鍒掓鏌ユ棩鏈熶负 <b>${plannedText}</b>锛屽綋鍓嶅鏍告棩鏈熸槸 <b>${todayStr}</b>锛屽睘浜�<b>鎻愬墠瀹℃牳</b>銆�</div>`
+      const items = [
+        `鏈疆璁板綍鐨勮鍒掓鏌ユ棩鏈熶繚鐣欎负 <b>${plannedText}</b> 涓嶅彉锛涘鏍搁�氳繃鍚庯紝銆屾牳鏌ユ椂闂淬�嶈褰曚负瀹為檯瀹℃牳鏃ユ湡 <b>${todayStr}</b>銆俙,
+        `璁惧妗f鐨勬渶杩戞牳鏌ユ棩鏈熸洿鏂颁负 <b>${todayStr}</b>锛屼笅娆℃牳鏌ユ棩鏈熸寜鏍告煡鍛ㄦ湡鑷姩璁$畻銆俙,
+        `绯荤粺浼氭寜璁惧鐨勬牳鏌ュ懆鏈熻嚜鍔ㄧ敓鎴愪笅涓�杞緟鏍告煡浠诲姟锛堝湪涓嬫鏍告煡鏃ユ湡鎵�灞炲勾浠界殑璁″垝涓級锛屽垵濮嬬姸鎬佲�滄湭寮�濮嬧�濓紝杩欐槸姝e父鐜拌薄锛屼笉鏄鏍告病鐢熸晥銆俙
+      ]
       const content = `${head}<div class="er-title">閫氳繃鍚庣郴缁熶細鍋氫笁浠朵簨锛�</div>` +
         `<ol class="er-list">${items.map(item => `<li>${item}</li>`).join('')}</ol>` +
         `<div class="er-question">鏄惁纭閫氳繃锛�</div>`
@@ -376,11 +369,11 @@
         dangerouslyUseHTMLString: true,
         customClass: 'early-review-message',
       }).then(() => {
-        this.submitReview(statue, isMonthOnly)
+        this.submitReview(statue)
       }).catch(() => {})
     },
     // 鐪熸鎻愪氦瀹℃牳
-    submitReview(statue, isMonthOnly = false) {
+    submitReview(statue) {
       this.submitFormLoading = true
       const params = {
         planDetailsId: this.form.planDetailsId,
@@ -388,12 +381,7 @@
       }
       reviewExamineRecord(params).then(res => {
         if (res.code == 200) {
-          if (statue === 1 && isMonthOnly) {
-            const now = new Date()
-            this.$message.success(`瀹℃牳閫氳繃锛屾湰杞凡褰掑叆 ${now.getFullYear()} 骞磋澶囨牳鏌ヨ鍒抈)
-          } else {
-            this.$message.success(statue === 1 ? '瀹℃牳閫氳繃' : '宸查��鍥�')
-          }
+          this.$message.success(statue === 1 ? '瀹℃牳閫氳繃' : '瀹℃牳涓嶉�氳繃')
           this.resetForm()
         }
         this.submitFormLoading = false
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue b/src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue
index 0c661a4..732cf21 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentMaintenance.vue
@@ -1,62 +1,110 @@
 <template>
+  <!--  璁惧缁存姢淇濆吇锛堝彧璇诲彴璐︼紝璁板綍鐢变繚鍏昏鍒掔敓鎴愶級-->
   <div>
     <div class="search">
       <el-button size="small" type="primary" @click="refreshTableList">鍒锋柊</el-button>
-      <el-button size="small" type="primary" @click="openDia('add')">鏂� 寤�</el-button>
       <el-button :loading="outLoading" size="small" type="primary" @click="openHandleOut">瀵� 鍑�</el-button>
     </div>
     <div>
-      <lims-table :tableData="tableData" :column="column"
-                  height="calc(100vh - 20em)" @pagination="pagination"
-                  :page="page" :tableLoading="tableLoading"></lims-table>
+      <el-table v-loading="tableLoading" :data="tableData" border height="calc(100vh - 20em)" style="width: 100%;">
+        <el-table-column align="center" header-align="center" label="搴忓彿" prop="prop" type="index"
+          width="60"></el-table-column>
+        <el-table-column align="center" header-align="center" label="缁存姢鏃ユ湡" min-width="110">
+          <template #default="scope">{{ formatDate(scope.row.maintenanceDate) }}</template>
+        </el-table-column>
+        <el-table-column align="center" header-align="center" label="缁存姢淇濆吇鍐呭">
+          <el-table-column v-for="item in checkColumns" :key="item.prop" align="center" header-align="center"
+            :label="item.label" width="110">
+            <template #default="scope">{{ scope.row[item.prop] || '鈥�' }}</template>
+          </el-table-column>
+        </el-table-column>
+        <el-table-column align="center" header-align="center" label="缁存姢浜�" min-width="100">
+          <template #default="scope">{{ scope.row.maintenanceUserName || '鈥�' }}</template>
+        </el-table-column>
+        <el-table-column label="瀹℃牳鐘舵��" min-width="100">
+          <template #default="scope">
+            <el-tag v-if="scope.row.recordStatus === 1" type="warning" disable-transitions>寰呭鏍�</el-tag>
+            <el-tag v-else-if="scope.row.recordStatus === 2" type="success" disable-transitions>閫氳繃</el-tag>
+            <el-tag v-else-if="scope.row.recordStatus === 3" type="danger" disable-transitions>涓嶉�氳繃</el-tag>
+            <el-tag v-else type="info" disable-transitions>鍘嗗彶</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="澶囨敞" min-width="140" show-overflow-tooltip>
+          <template #default="scope">{{ scope.row.remark || '鈥�' }}</template>
+        </el-table-column>
+        <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="120">
+          <template #default="scope">
+            <el-button size="small" link type="primary" @click="handleView(scope.row)">鏌ョ湅</el-button>
+            <el-button v-if="scope.row.recordStatus === 1 || scope.row.recordStatus === 3" size="small" link
+              type="danger" @click="handleDeleteClick(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination :current-page="pagination.current" :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>
     </div>
-    <el-dialog v-model="dialogVisible" title="浠櫒璁惧浣跨敤缁存姢淇濆吇琛�" width="55%">
-      <el-form ref="form" :model="form" label-width="130px" :rules="rules">
+    <el-dialog :close-on-click-modal="false" v-model="dialogVisible" title="鏌ョ湅淇濆吇璁板綍" width="880px">
+      <el-form :model="form" label-width="150px" size="small">
         <el-row>
           <el-col :span="12">
-            <el-form-item label="缁存姢鏃ユ湡:" prop="maintenanceDate">
-              <el-date-picker v-model="form.maintenanceDate" :disabled="operationType === 'view'"
-                              format="YYYY-MM-DD" size="small" placeholder="閫夋嫨鏃ユ湡" style="width:100%"
-                              type="date" value-format="YYYY-MM-DD">
-              </el-date-picker>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="缁存姢鍐呭:" prop="maintenanceContentArr">
-              <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>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="缁存姢浜�:" prop="maintenanceUserId">
-              <el-select v-model="form.maintenanceUserId"
-                         clearable filterable
-                         placeholder="璇烽�夋嫨" size="small" style="width: 100%;">
-                <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id">
-                </el-option>
-              </el-select>
+            <el-form-item label="璁惧鍚嶇О锛�">
+              <el-input v-model="form.deviceName" disabled></el-input>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="澶囨敞:" prop="remark">
-              <el-input v-model="form.remark" :disabled="operationType === 'view'" size="small"
-                        style="width: 100%;"></el-input>
+            <el-form-item label="璁惧缂栧彿锛�">
+              <el-input v-model="form.managementNumber" disabled></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="缁存姢鏃ユ湡锛�">
+              <el-input v-model="form.maintenanceDate" disabled></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="缁存姢浜猴細">
+              <el-input v-model="form.maintenanceUserName" disabled></el-input>
             </el-form-item>
           </el-col>
         </el-row>
+        <div class="form-section-title">缁存姢淇濆吇鍐呭</div>
+        <el-row>
+          <el-col v-for="item in checkColumns" :key="item.prop" :span="12">
+            <el-form-item :label="item.label + '锛�'">
+              <el-input v-model="form[item.prop]" disabled></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="淇濆吇澶囨敞锛�">
+          <el-input v-model="form.remark" :rows="2" disabled type="textarea"></el-input>
+        </el-form-item>
+        <el-form-item label="瀹℃牳鐘舵�侊細">
+          <el-tag v-if="form.recordStatus === 1" type="warning" disable-transitions>寰呭鏍�</el-tag>
+          <el-tag v-else-if="form.recordStatus === 2" type="success" disable-transitions>閫氳繃</el-tag>
+          <el-tag v-else-if="form.recordStatus === 3" type="danger" disable-transitions>涓嶉�氳繃</el-tag>
+          <el-tag v-else type="info" disable-transitions>鍘嗗彶</el-tag>
+        </el-form-item>
+        <el-row v-if="form.reviewUserName || form.reviewTime">
+          <el-col :span="12">
+            <el-form-item label="瀹℃牳浜猴細">
+              <el-input v-model="form.reviewUserName" disabled></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="瀹℃牳鏃堕棿锛�">
+              <el-input v-model="form.reviewTime" disabled></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item v-if="form.reviewRemark" label="瀹℃牳鎰忚锛�">
+          <el-input v-model="form.reviewRemark" :rows="2" disabled type="textarea"></el-input>
+        </el-form-item>
       </el-form>
-      <template #footer><span  class="dialog-footer">
-        <el-button @click="closeDia">鍙� 娑�</el-button>
-        <el-button v-if="operationType !== 'view'" type="primary" @click="saveRecord" :loading="buttonLoading">纭� 瀹�</el-button>
+      <template #footer><span class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍏� 闂�</el-button>
       </span></template>
     </el-dialog>
   </div>
@@ -64,18 +112,28 @@
 
 <script>
 import {
-  addDeviceMaintenance,
-  deleteDeviceMaintenance, exportDeviceMaintenance,
-  selectDeviceMaintenancePage
-} from "@/api/cnas/resourceDemand/device";
-import limsTable from "@/components/Table/lims-table.vue";
-import {selectUserCondition} from "@/api/system/user";
-import {saveBlobOrShowError} from '@/utils/saveBlob'
+  deleteDeviceMaintenance,
+  exportDeviceMaintenance,
+  selectDeviceMaintenancePage,
+} from '@/api/cnas/resourceDemand/device'
+import { formatDateOnly, formatListDate } from './dateFormat'
+import { saveBlobOrShowError } from '@/utils/saveBlob'
+
+// 缁存姢淇濆吇妫�鏌ラ」锛屼笌浠櫒璁惧缁存姢淇濆吇璁板綍琛ㄤ竴鑷�
+const CHECK_ITEMS = [
+  { label: '澶栬鏄惁鑹ソ', prop: 'appearanceGood' },
+  { label: '鏄惁鍙互姝e父浣跨敤', prop: 'normalUse' },
+  { label: '鏄惁娓呮磥浠櫒琛ㄩ潰', prop: 'surfaceClean' },
+  { label: '鏍囪瘑鏄惁瀹屽ソ', prop: 'labelIntact' },
+  { label: '鏄剧ず鍣ㄧ伅鏄惁姝e父', prop: 'displayLightNormal' },
+  { label: '浠櫒鏄惁鐢熼攬', prop: 'noRust' },
+  { label: '鏍″噯鏄惁姝e父', prop: 'calibrationNormal' },
+  { label: '閰嶄欢鏄惁闇�瑕佹洿鎹�', prop: 'partsReplace' },
+  { label: '缁存姢缁撴灉鏄惁姝e父', prop: 'resultNormal' },
+]
 
 export default {
-  name: '',
-  // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
-  components: {limsTable},
+  name: 'equipment-maintenance',
   props: {
     clickNodeVal: {
       type: Object,
@@ -85,170 +143,97 @@
     },
   },
   data() {
-    // 杩欓噷瀛樻斁鏁版嵁
     return {
-      search: {
-        maintenanceDate: '',
-      },
       outLoading: false,
       tableData: [],
       tableLoading: false,
-      page: {
+      pagination: {
         total: 0,
         size: 20,
-        current: 1
+        current: 1,
       },
-      column: [
-        { label: '缁存姢鏃ユ湡', prop: 'maintenanceDate' },
-        { label: '缁存姢鍐呭', prop: 'maintenanceContent' },
-        { label: '缁存姢浜�', prop: 'maintenanceUserName' },
-        { label: '澶囨敞', prop: 'remark' },
-        {
-          dataType: 'action',
-          label: '鎿嶄綔',
-          operation: [
-            {
-              name: '缂栬緫',
-              type: 'text',
-              clickFun: (row) => {
-                this.openDia('edit', row);
-              },
-            },
-            {
-              name: '鍒犻櫎',
-              type: 'text',
-              clickFun: (row) => {
-                this.handleDeleteClick(row);
-              },
-            },
-          ]
-        }
-      ],
+      checkColumns: CHECK_ITEMS.map(item => ({ ...item })),
       dialogVisible: false,
-      form: {
-        id: '',
-        deviceId: '',
-        maintenanceDate: '',
-        maintenanceContentArr: [],
-        maintenanceContent: '',
-        maintenanceContentText: '',
-        maintenanceUserId: '',
-        remark: '',
-      },
-      operationType: '',
-      buttonLoading: false,
-      qualificationList: [],
-      rules: {
-        maintenanceDate: [{ 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: [],
+      form: {},
     };
   },
   mounted() {
     this.refreshTableList()
   },
-  // 鏂规硶闆嗗悎
   methods: {
     // 鐐瑰嚮鍒锋柊
-    refreshTableList () {
-      this.page.current = 1;
+    refreshTableList() {
+      this.pagination.current = 1
       this.getTableList()
     },
-    // 鍒嗛〉鍒囨崲
-    pagination(page) {
-      this.page.current = page.page
-      this.page.size = page.limit
+    formatDate(value) {
+      return formatDateOnly(value) || '鈥�'
+    },
+    // 鍒嗛〉
+    handleSizeChange(val) {
+      this.pagination.size = val
       this.getTableList()
     },
-    getTableList () {
+    // 鍒嗛〉
+    handleCurrentChange(val) {
+      this.pagination.current = val
+      this.getTableList()
+    },
+    getTableList() {
+      if (!this.clickNodeVal.value) {
+        this.tableData = []
+        this.pagination.total = 0
+        return
+      }
       this.tableLoading = true
       selectDeviceMaintenancePage({
         deviceId: this.clickNodeVal.value,
-        ...this.page
+        current: this.pagination.current,
+        size: this.pagination.size,
       }).then(res => {
         this.tableLoading = false
-        this.tableData = res.data.records
-        this.page.total = res.data.total
-      }).catch(err => {
+        if (res.code == 200) {
+          this.tableData = res.data.records || []
+          this.pagination.total = res.data.total || 0
+        }
+      }).catch(() => {
         this.tableLoading = false
       })
     },
-    // 鎵撳紑鎿嶄綔寮规
-    openDia (type, row) {
-      this.operationType = type
-      this.dialogVisible = true
-      this.$nextTick(() => {
-        this.$refs['form'].resetFields()
-        this.form.id = ''
-        if (this.operationType === 'edit') {
-          this.form = {...row}
-          this.form['maintenanceContentArr'] = this.form.maintenanceContent ? this.form.maintenanceContent.split(',') : []
-          this.form['maintenanceContentText'] = this.form.maintenanceContent || ''
-        }
-      })
-      this.getDictS()
-      this.getUserList()
-    },
-    // 鏌ヨ缁存姢鍐呭閫夋嫨妗嗗唴瀹�
-    getDictS () {
-      // 瀹氫箟瀹為獙瀹ゅ悕绉颁笌缁存姢鍐呭绫诲瀷鐨勬槧灏勫叧绯�
-      const labTypeMapping = {
-        '鑰佸寲瀹�': 'aging_maintenance_content',
-        '鑰佸寲瀹為獙瀹�': 'aging_maintenance_content',
-        '鐢垫�ц兘瀹為獙瀹�': 'electrical_maintenance_content',
-        '鐜瀹為獙瀹�': 'environmental_maintenance_content',
-        '鐕冪儳瀹為獙瀹�': 'burn_maintenance_content',
-        '娣风偧瀹為獙瀹�': 'mixing_maintenance_content',
-        '妫�娴嬩腑蹇冪數鎬ц兘瀹為獙瀹�': 'center_electrical_maintenance_content',
-        '鎭掓俯浜�': 'temperature2_maintenance_content',
-        '鎭掓俯涓�': 'temperature1_maintenance_content',
-        '鍖栧瀹為獙瀹�': 'chemistry_maintenance_content',
-        '鍒舵牱瀹�': 'sample_maintenance_content',
-        '浣庢俯瀹為獙瀹�': 'hypothermia_maintenance_content',
-      };
-      // 鍙栬澶囧瓨鏀剧偣鍚嶇О浣滀负鏄犲皠閿�
-      const name = this.clickNodeVal.storagePoint || '鍏朵粬';
-      // 鏍规嵁鏄犲皠鍏崇郴鑾峰彇瀵瑰簲鐨勭被鍨�
-      const type = labTypeMapping[name];
-      if (!type) {
-        this.qualificationList = [];
-        return;
+    // 鏌ョ湅淇濆吇璁板綍锛堝彧璇伙級
+    handleView(row) {
+      this.form = {
+        deviceName: row.deviceName || '',
+        managementNumber: row.managementNumber || '',
+        maintenanceDate: formatDateOnly(row.maintenanceDate),
+        maintenanceUserName: row.maintenanceUserName || '',
+        remark: row.remark || '',
+        reviewUserName: row.reviewUserName || '',
+        reviewTime: formatListDate(row.reviewTime) || '',
+        reviewRemark: row.reviewRemark || '',
+        recordStatus: row.recordStatus,
       }
-      this.getDicts(type).then((response) => {
-        this.qualificationList = response.data.map((m) => {
-          return {
-            label: m.dictLabel,
-            value: m.dictValue,
-          };
-        });
-      });
+      this.checkColumns.forEach(item => {
+        this.form[item.prop] = row[item.prop] || ''
+      })
+      this.dialogVisible = true
     },
-    openHandleOut () {
+    openHandleOut() {
+      if (!this.clickNodeVal.value) {
+        this.$message.warning('璇峰厛閫夋嫨璁惧')
+        return
+      }
       this.outLoading = true
       exportDeviceMaintenance({
         deviceId: this.clickNodeVal.value
       }).then(res => {
         this.outLoading = false
-        saveBlobOrShowError(res, '璁惧缁存姢淇濆吇.doc', 'application/msword')
+        saveBlobOrShowError(res, '浠櫒璁惧缁存姢淇濆吇璁板綍.docx', 'application/msword')
       }).catch(() => {
         this.outLoading = false
       })
-
     },
+    // 鍙厑璁稿垹闄ゅ緟瀹℃牳/涓嶉�氳繃鐨勮褰曪紙鍘嗗彶涓庡鏍搁�氳繃璁板綍鐣欐。锛�
     handleDeleteClick(row) {
       this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ潯淇濆吇璁板綍, 鏄惁缁х画?', '鎻愮ず', {
         confirmButtonText: '纭畾',
@@ -260,7 +245,7 @@
             type: 'success',
             message: '鍒犻櫎鎴愬姛!'
           });
-          this.refreshTableList()
+          this.getTableList()
         })
       }).catch(() => {
         this.$message({
@@ -269,46 +254,11 @@
         });
       });
     },
-    // 鎻愪氦鏂板鍜屼繚瀛�
-    saveRecord () {
-      this.$refs.form.validate((valid) => {
-        if (valid) {
-          this.buttonLoading = true;
-          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;
-            this.$message.success('鏂板鎴愬姛')
-            this.closeDia()
-            this.getTableList()
-          }).catch(err => {
-            this.buttonLoading = false;
-          })
-        }
-      })
-    },
-    closeDia () {
-      this.$refs['form'].resetFields();
-      this.dialogVisible = false
-      this.refreshTableList()
-    },
-    // 鑾峰彇璐熻矗浜轰俊鎭帴鍙�
-    getUserList() {
-      selectUserCondition({type: 2}).then(res => {
-        if (res.code == 200) {
-          this.responsibleOptions = res.data
-        }
-      })
-    },
   },
   watch: {
     // 鐩戝惉鐐瑰嚮el-tree鐨勬暟鎹紝杩涜鏁版嵁鍒锋柊
     clickNodeVal(newVal) {
-      if (newVal.value) {
-        this.refreshTableList();
-      }
+      this.refreshTableList();
     },
   }
 };
@@ -316,8 +266,19 @@
 
 <style scoped>
 .search {
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
   height: 46px;
-  text-align: right;
   margin-top: 10px;
 }
+
+.form-section-title {
+  font-size: 14px;
+  font-weight: 600;
+  color: var(--lims-text);
+  margin: 4px 0 16px;
+  padding-left: 8px;
+  border-left: 4px solid var(--el-color-primary);
+}
 </style>
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue b/src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue
index 0c19357..2eea398 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentMaintenancePlan.vue
@@ -10,7 +10,7 @@
           </el-select>
         </div>
         <div>
-          <el-button size="small" type="primary" @click="loadPlan">鍒锋柊</el-button>
+          <el-button size="small" type="primary" @click="loadYearOptions(true)">鍒锋柊</el-button>
           <el-button size="small" type="primary" :loading="outLoading" @click="handleDownOne">瀵煎嚭</el-button>
         </div>
       </div>
@@ -47,25 +47,45 @@
         :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>
+        <el-table-column label="璁惧鍚嶇О" min-width="150" prop="deviceName" show-overflow-tooltip></el-table-column>
+        <el-table-column label="璁惧鍨嬪彿" min-width="130" prop="specificationModel" show-overflow-tooltip></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 align="center" header-align="center" label="瀹℃牳鏃ユ湡" min-width="110">
+          <template #default="scope">{{ formatReviewDate(scope.row) }}</template>
+        </el-table-column>
+        <el-table-column align="center" header-align="center" label="缁存姢淇濆吇鍐呭">
+          <el-table-column v-for="item in checkColumns" :key="item.prop" align="center" header-align="center"
+            :label="item.label" width="110">
+            <template #default="scope">{{ scope.row[item.prop] || '鈥�' }}</template>
+          </el-table-column>
+        </el-table-column>
+        <el-table-column align="center" header-align="center" label="缁存姢浜�" min-width="100">
+          <template #default="scope">{{ scope.row.maintenanceUserName || '鈥�' }}</template>
+        </el-table-column>
+        <el-table-column label="瀹℃牳鐘舵��" min-width="100">
           <template #default="scope">
-            {{ scope.row.deviceName }}{{ scope.row.specificationModel ? ' ' + scope.row.specificationModel : '' }}
+            <el-tag v-if="!scope.row.recordStatus" type="info" disable-transitions>鏈紑濮�</el-tag>
+            <el-tag v-else-if="scope.row.recordStatus === 1" type="warning" disable-transitions>寰呭鏍�</el-tag>
+            <el-tag v-else-if="scope.row.recordStatus === 2" type="success" disable-transitions>閫氳繃</el-tag>
+            <el-tag v-else-if="scope.row.recordStatus === 3" type="danger" disable-transitions>涓嶉�氳繃</el-tag>
           </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">
+        <el-table-column label="澶囨敞" min-width="140" show-overflow-tooltip>
+          <template #default="scope">{{ scope.row.recordRemark || '鈥�' }}</template>
+        </el-table-column>
+        <el-table-column align="center" fixed="right" label="鎿嶄綔" min-width="300">
           <template #default="scope">
             <el-button size="small" link type="primary"
+              :disabled="scope.row.recordStatus === 2 || scope.row.recordStatus === 3"
               @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="deleteRow(scope.row)">鍒犻櫎</el-button>
+            <el-button size="small" link type="primary" :disabled="!scope.row.recordId"
+              @click="handleForm('view', scope.row)">鏌ョ湅</el-button>
+            <el-button v-if="scope.row.recordStatus === 0 || scope.row.recordStatus === 1"
+              size="small" link type="primary" :disabled="!scope.row.maintenanceUserName"
+              @click="handleReview(scope.row)">瀹℃牳</el-button>
+            <el-button v-if="scope.row.recordStatus !== 2"
+              size="small" link type="danger" @click="deleteRow(scope.row)">鍒犻櫎</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -76,55 +96,76 @@
       </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">
+      :title="dialogTitle" width="880px" @close="resetForm">
+      <el-form ref="modelForm" :model="form" :rules="rules" label-width="150px" size="small">
         <el-row>
           <el-col :span="12">
             <el-form-item label="璁惧鍚嶇О锛�">
-              <el-input v-model="form.deviceName" disabled size="small"></el-input>
+              <el-input v-model="form.deviceName" disabled></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="璁惧鍨嬪彿锛�">
+              <el-input v-model="form.specificationModel" disabled></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-input v-model="form.deviceNumber" disabled></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 label="瀛樻斁鐐癸細">
+              <el-input v-model="form.storagePoint" disabled></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>
-            </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>
-            </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"
+            <el-form-item label="缁存姢鏃ユ湡锛�" prop="maintenanceDate">
+              <el-date-picker v-model="form.maintenanceDate" :disabled="!isEdit" clearable
+                format="YYYY-MM-DD" placeholder="閫夋嫨鏃ユ湡" style="width: 100%" type="date"
                 value-format="YYYY-MM-DD"></el-date-picker>
             </el-form-item>
           </el-col>
+          <el-col :span="12">
+            <el-form-item label="缁存姢浜猴細" prop="maintenanceUserId">
+              <el-select v-model="form.maintenanceUserId" :disabled="!isEdit" clearable filterable
+                placeholder="璇烽�夋嫨" style="width: 100%">
+                <el-option v-for="item in maintainerOptions" :key="item.id" :label="item.name"
+                  :value="item.id"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
         </el-row>
+        <div class="form-section-title">缁存姢淇濆吇鍐呭</div>
+        <el-row>
+          <el-col v-for="item in checkColumns" :key="item.prop" :span="12">
+            <el-form-item :label="item.label + '锛�'" :prop="item.prop">
+              <el-radio-group v-model="form[item.prop]" :disabled="!isEdit">
+                <el-radio value="鈭�">鈭�</el-radio>
+                <el-radio value="脳">脳</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="淇濆吇澶囨敞锛�">
+          <el-input v-model="form.remark" :disabled="!isEdit" :rows="2" placeholder="鍙~鍐欎繚鍏诲娉�"
+            type="textarea"></el-input>
+        </el-form-item>
+        <el-form-item v-if="operationType === 'review'" label="瀹℃牳澶囨敞锛�">
+          <el-input v-model="form.reviewRemark" :rows="2" placeholder="鍙~鍐欏鏍告剰瑙�"
+            type="textarea"></el-input>
+        </el-form-item>
+        <div class="check-note">澶囨敞锛氭甯搞�佽壇濂芥墦鈥溾垰鈥濓紝涓嶆甯稿強鍚︽墦鈥溍椻�濄��</div>
+        <div v-if="cycleNote" class="check-note">{{ cycleNote }}</div>
       </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>
+        <template v-if="operationType === 'review'">
+          <el-button :loading="reviewLoading" @click="submitReview(0)">涓嶉�氳繃</el-button>
+          <el-button :loading="reviewLoading" type="primary" @click="submitReview(1)">閫� 杩�</el-button>
+        </template>
+        <el-button v-else-if="operationType === 'edit'" :loading="submitFormLoading" type="primary"
+          @click="submitForm">纭� 璁�</el-button>
       </span></template>
     </el-dialog>
   </div>
@@ -132,15 +173,32 @@
 
 <script>
 import {
-  selectDeviceMaintenancePlanByPage,
+  getMaintenancePlanYears,
   getMaintenancePlanByYear,
   pageMaintenancePlanDetail,
-  updateMaintenancePlanDetail,
   deleteMaintenancePlanDetail,
   exportDeviceMaintenancePlan,
+  addDeviceMaintenance,
+  reviewDeviceMaintenance,
 } from '@/api/cnas/resourceDemand/device.js'
+import { selectUserCondition } from '@/api/system/user'
+import dayjs from 'dayjs'
 import { formatDateOnly } from './dateFormat'
 import { saveBlobOrShowError } from '@/utils/saveBlob'
+
+// 缁存姢淇濆吇妫�鏌ラ」锛屼笌浠櫒璁惧缁存姢淇濆吇璁板綍琛ㄤ竴鑷�
+const CHECK_ITEMS = [
+  { label: '澶栬鏄惁鑹ソ', prop: 'appearanceGood' },
+  { label: '鏄惁鍙互姝e父浣跨敤', prop: 'normalUse' },
+  { label: '鏄惁娓呮磥浠櫒琛ㄩ潰', prop: 'surfaceClean' },
+  { label: '鏍囪瘑鏄惁瀹屽ソ', prop: 'labelIntact' },
+  { label: '鏄剧ず鍣ㄧ伅鏄惁姝e父', prop: 'displayLightNormal' },
+  { label: '浠櫒鏄惁鐢熼攬', prop: 'noRust' },
+  { label: '鏍″噯鏄惁姝e父', prop: 'calibrationNormal' },
+  { label: '閰嶄欢鏄惁闇�瑕佹洿鎹�', prop: 'partsReplace' },
+  { label: '缁存姢缁撴灉鏄惁姝e父', prop: 'resultNormal' },
+]
+
 export default {
   name: "equipment-maintenance-plan",
   props: {
@@ -152,6 +210,10 @@
     }
   },
   data() {
+    const rules = {
+      maintenanceDate: [{ required: true, message: '璇烽�夋嫨缁存姢鏃ユ湡', trigger: 'change' }],
+      maintenanceUserId: [{ required: true, message: '璇烽�夋嫨缁存姢浜�', trigger: 'change' }],
+    }
     return {
       planYear: '',
       yearOptions: [],
@@ -167,40 +229,38 @@
         current: 1,
         total: 0,
       },
+      checkColumns: CHECK_ITEMS.map(item => ({ ...item })),
       dialogVisible: false,
       operationType: '',
       form: {},
-      rules: {
-        maintenanceDate: [{ required: true, message: '璇烽�夋嫨璁″垝淇濆吇鏃堕棿', trigger: 'change' }],
-      },
+      rules,
       submitFormLoading: false,
       outLoading: false,
+      reviewLoading: false,
+      userOptions: [],
     }
   },
   mounted() {
     this.loadYearOptions()
+    this.getUserList()
   },
   methods: {
-    // 骞翠唤涓嬫媺閫夐」锛氬凡鏈夎鍒掑勾浠� + 褰撳墠骞翠唤
-    loadYearOptions() {
+    // 骞翠唤涓嬫媺锛氬彧鍒楀嚭鏈夋槑缁嗙殑骞翠唤锛堢┖骞翠唤璁″垝鐢卞悗绔垹闄わ級锛岄粯璁ゆ樉绀烘湰骞村害锛堟湰骞村害鏃犺鍒掓椂閫�鍥炴渶鏂板勾浠斤級
+    loadYearOptions(preserveYear = false) {
       const currentYear = String(new Date().getFullYear())
       const finish = (years) => {
-        if (years.indexOf(currentYear) === -1) {
-          years.push(currentYear)
+        let list = [...new Set(years.map(y => String(y)).filter(Boolean))]
+        list.sort((a, b) => b.localeCompare(a))
+        if (!list.length) {
+          list = [currentYear]
         }
-        this.yearOptions = [...new Set(years)].sort((a, b) => b.localeCompare(a))
-        this.planYear = currentYear
+        this.yearOptions = list
+        const keep = preserveYear && this.planYear && list.includes(String(this.planYear))
+        this.planYear = keep ? String(this.planYear) : (list.includes(currentYear) ? currentYear : list[0])
         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)
+      getMaintenancePlanYears().then(res => {
+        finish(res.code == 200 ? (res.data || []) : [])
       }).catch(() => {
         finish([])
       })
@@ -251,9 +311,10 @@
         this.tableLoading = false
       })
     },
-    // 鍒扮偣闇�淇濆吇鐨勮鏍囩孩
-    formatDateCell(row, column, cellValue) {
-      return formatDateOnly(cellValue)
+    // 鏈鏍告樉绀鸿鍒掍繚鍏绘椂闂达紱瀹℃牳閫氳繃鍚庢樉绀哄鏍稿綋澶╋紙涓庢牳鏌ヨ鍒掍竴鑷达級
+    formatReviewDate(row) {
+      const date = row.reviewStatus === 1 ? row.reviewTime : row.maintenanceDate
+      return formatDateOnly(date) || '鈥�'
     },
     tableRowClassName({ row }) {
       return row.redFlag === 1 ? 'red-row' : ''
@@ -276,10 +337,10 @@
       this.pagination1.current = val
       this.getTableList()
     },
-    // 鎵撳紑鏄庣粏寮规
+    // 鎵撳紑鏄庣粏寮规锛歟dit 濉啓/淇敼淇濆吇璁板綍锛寁iew 鏌ョ湅锛宺eview 瀹℃牳
     handleForm(type, row) {
       this.operationType = type
-      this.form = this.HaveJson(row)
+      this.form = this.buildForm(row)
       this.dialogVisible = true
       this.$nextTick(() => {
         if (this.$refs.modelForm) {
@@ -287,31 +348,60 @@
         }
       })
     },
-    // 鎻愪氦琛ㄥ崟锛堝彧鍥炰紶鏄庣粏琛ㄥ瓧娈碉級
+    buildForm(row) {
+      const form = {
+        id: row.recordId || null,
+        maintenancePlanDetailId: row.maintenancePlanDetailId,
+        deviceId: row.deviceId,
+        deviceName: row.deviceName,
+        specificationModel: row.specificationModel,
+        deviceNumber: row.deviceNumber,
+        storagePoint: row.storagePoint,
+        // 宸叉湁璁板綍鐢ㄨ褰曟棩鏈燂紱杩樻病璁板綍鏃堕粯璁や粖澶╋紝閬垮厤鎶婅鍒掓棩鏈熷綋鎴愬疄闄呬繚鍏绘棩鏈�
+        maintenanceDate: row.recordId
+          ? formatDateOnly(row.recordMaintenanceDate)
+          : dayjs().format('YYYY-MM-DD'),
+        maintenanceCycle: row.maintenanceCycle || row.maintenanceIntervals || '',
+        maintenanceUserId: row.maintenanceUserId || '',
+        maintenanceUserName: row.maintenanceUserName || '',
+        remark: row.recordRemark || '',
+        reviewRemark: '',
+      }
+      this.checkColumns.forEach(item => {
+        form[item.prop] = row[item.prop] || ''
+      })
+      return form
+    },
+    // 淇濆瓨淇濆吇璁板綍锛堟柊澧炴垨淇敼鍚庤繘鍏ュ緟瀹℃牳锛�
     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
-          })
+        if (!valid) {
+          return
         }
+        this.submitFormLoading = true
+        const payload = {
+          maintenancePlanDetailId: this.form.maintenancePlanDetailId,
+          deviceId: this.form.deviceId,
+          maintenanceDate: this.form.maintenanceDate,
+          maintenanceUserId: this.form.maintenanceUserId,
+          remark: this.form.remark,
+        }
+        if (this.form.id) {
+          payload.id = this.form.id
+        }
+        this.checkColumns.forEach(item => {
+          payload[item.prop] = this.form[item.prop]
+        })
+        addDeviceMaintenance(payload).then(res => {
+          this.submitFormLoading = false
+          if (res.code == 200) {
+            this.$message.success(this.form.id ? '淇敼鎴愬姛' : '淇濆瓨鎴愬姛')
+            this.dialogVisible = false
+            this.loadPlan()
+          }
+        }).catch(() => {
+          this.submitFormLoading = false
+        })
       })
     },
     resetForm() {
@@ -319,14 +409,15 @@
     },
     // 鏄庣粏-鍒犻櫎
     deleteRow(row) {
-      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ潯鏄庣粏, 鏄惁缁х画?', '鎻愮ず', {
+      this.$confirm('鍒犻櫎鍚庯紝璇ヨ鐨勪繚鍏昏褰曪紙鏈鏍告垨瀹℃牳涓嶉�氳繃锛変細涓�骞跺垹闄わ紝鏄惁缁х画?', '鎻愮ず', {
         confirmButtonText: '纭畾',
         cancelButtonText: '鍙栨秷',
         type: 'warning'
       }).then(() => {
         deleteMaintenancePlanDetail({ maintenancePlanDetailId: row.maintenancePlanDetailId }).then(() => {
           this.$message.success('鍒犻櫎鎴愬姛锛�');
-          this.getTableList()
+          // 鍒犲畬鍙兘鏄骞翠唤鏈�鍚庝竴鏉★紝閲嶆柊鍙栧勾浠斤紝绌哄勾浠戒細涓�骞舵竻鎺�
+          this.loadYearOptions(true)
         });
       }).catch(() => {
         this.$message({
@@ -344,12 +435,91 @@
       }).catch(() => {
         this.outLoading = false
       })
-    }
+    },
+    // 鎵撳紑淇濆吇璁板綍瀹℃牳寮规
+    handleReview(row) {
+      this.handleForm('review', row)
+    },
+    // 鎻愪氦瀹℃牳缁撴灉锛�1 閫氳繃锛�0 涓嶉�氳繃
+    submitReview(status) {
+      this.reviewLoading = true
+      reviewDeviceMaintenance({
+        maintenancePlanDetailId: this.form.maintenancePlanDetailId,
+        reviewStatus: status,
+        reviewRemark: this.form.reviewRemark,
+      }).then(res => {
+        this.reviewLoading = false
+        if (res.code == 200) {
+          this.$message.success(status === 1 ? '瀹℃牳閫氳繃' : '瀹℃牳涓嶉�氳繃')
+          this.dialogVisible = false
+          // 瀹℃牳閫氳繃鍚庢槑缁嗕細褰掑埌瀹℃牳骞翠唤鐨勮鍒掞紝閲嶆柊鍙栧勾浠介伩鍏嶅仠鍦ㄤ笉瀛樺湪鐨勫勾浠�
+          this.loadYearOptions(true)
+        }
+      }).catch(() => {
+        this.reviewLoading = false
+      })
+    },
+    // 缁存姢浜轰笅鎷�
+    getUserList() {
+      selectUserCondition({ type: 2 }).then(res => {
+        if (res.code == 200) {
+          this.userOptions = res.data || []
+        }
+      })
+    },
   },
   computed: {
     // 鏄惁宸插畬鎴愬鏍革紙閫氳繃/涓嶉�氳繃锛�
     isAudited() {
       return this.planInfo.status === 0 || this.planInfo.status === 1;
+    },
+    // 浠呯紪杈戠姸鎬佸彲濉啓琛ㄥ崟
+    isEdit() {
+      return this.operationType === 'edit'
+    },
+    // 鎸夎澶囨。妗堢殑淇濆吇鍛ㄦ湡锛堟湀锛夌敓鎴愬簳閮ㄨ鏄�
+    cycleNote() {
+      const months = parseInt((this.form && this.form.maintenanceCycle) || '', 10)
+      if (!months || months <= 0) {
+        return ''
+      }
+      if (months === 1) {
+        return '姝よ澶囩淮鎶や繚鍏绘瘡鏈� 1 娆°��'
+      }
+      if (months === 3) {
+        return '姝よ澶囩淮鎶や繚鍏绘瘡瀛e害 1 娆°��'
+      }
+      if (months === 6) {
+        return '姝よ澶囩淮鎶や繚鍏绘瘡鍗婂勾 1 娆°��'
+      }
+      if (months === 12) {
+        return '姝よ澶囩淮鎶や繚鍏绘瘡骞� 1 娆°��'
+      }
+      if (months % 12 === 0) {
+        return `姝よ澶囩淮鎶や繚鍏绘瘡 ${months / 12} 骞� 1 娆°�俙
+      }
+      return `姝よ澶囩淮鎶や繚鍏绘瘡 ${months} 涓湀 1 娆°�俙
+    },
+    dialogTitle() {
+      if (this.operationType === 'view') {
+        return '鏌ョ湅淇濆吇璁板綍'
+      }
+      if (this.operationType === 'review') {
+        return '淇濆吇璁板綍瀹℃牳'
+      }
+      return '缂栬緫淇濆吇璁板綍'
+    },
+    // 宸查�夌淮鎶や汉涓嶅湪褰撳墠浜哄憳鍒楄〃鏃惰ˉ涓�鏉★紝淇濊瘉涓嬫媺鑳芥樉绀哄鍚�
+    maintainerOptions() {
+      const list = this.userOptions.slice()
+      const form = this.form || {}
+      if (form.maintenanceUserId && !list.some(item => item.id === form.maintenanceUserId)) {
+        list.unshift({
+          id: form.maintenanceUserId,
+          name: form.maintenanceUserName || String(form.maintenanceUserId),
+        })
+      }
+      return list
     },
   },
 }
@@ -407,6 +577,22 @@
   margin-bottom: 10px;
 }
 
+.form-section-title {
+  font-size: 14px;
+  font-weight: 600;
+  color: var(--lims-text);
+  margin: 4px 0 16px;
+  padding-left: 8px;
+  border-left: 4px solid var(--el-color-primary);
+}
+
+.check-note {
+  font-size: 13px;
+  color: #909399;
+  line-height: 22px;
+  padding-left: 150px;
+}
+
 :deep(.red-row td) {
   background: #ffcccc !important;
 }
diff --git a/src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue b/src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue
index 975d0d1..119dd16 100644
--- a/src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue
+++ b/src/views/CNAS/resourceDemand/device/component/equipmentVerificationPlan.vue
@@ -52,8 +52,11 @@
         <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="deviceModel" 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="120">
+          <template #default="scope">
+            {{ scope.row.completeDate || formatCheckMonth(null, null, scope.row.checkTime) }}
+          </template>
+        </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>
@@ -90,7 +93,7 @@
               @click="handleRecord(scope.row)">瀹℃牳</el-button>
             <el-button v-if="scope.row.recordStatus === 2 || scope.row.recordStatus === 3"
               size="small" link type="primary" @click="handleDown(scope.row)">瀵煎嚭</el-button>
-            <el-button v-if="scope.row.recordStatus === 0 || scope.row.recordStatus === 1"
+            <el-button v-if="scope.row.recordStatus !== 2"
               size="small" link type="danger" @click="deleteFun1(scope.row.planDetailsId)">鍒犻櫎</el-button>
           </template>
         </el-table-column>
@@ -239,7 +242,7 @@
             <span class="export-panel-label">璁惧鍚嶇О</span>{{ downRow.deviceName || '鈥�' }}
           </div>
           <div class="export-panel-item">
-            <span class="export-panel-label">鏍告煡鏃堕棿</span>{{ formatCheckMonth(null, null, downRow.checkTime) || '鈥�' }}
+            <span class="export-panel-label">鏍告煡鏃堕棿</span>{{ downRow.completeDate || formatCheckMonth(null, null, downRow.checkTime) || '鈥�' }}
           </div>
         </div>
         <div v-if="!canExport" class="export-panel-tip">
@@ -264,8 +267,8 @@
 import CheckRecord from "./checkRecord.vue";
 import LimsAttachment from '@/components/Attachment/lims-attachment.vue'
 import {
-  pageDeviceExaminePlan,
   getExaminePlanByYear,
+  getExaminePlanYears,
   exportDeviceExaminePlanDetail,
   delDeviceExaminePlanDetail,
   pageDeviceExaminePlanDetail,
@@ -345,30 +348,24 @@
   },
   // 鏂规硶闆嗗悎
   methods: {
-    // 骞翠唤涓嬫媺鍙繚鐣欐湁璁″垝鏄庣粏鐨勫勾浠斤紝绌哄勾浠借嚜鍔ㄦ秷澶�
+    // 骞翠唤涓嬫媺鍙繚鐣欐湁璁″垝鏄庣粏鐨勫勾浠斤紝绌哄勾浠借鍒掕嚜鍔ㄥ垹闄わ紝榛樿鏄剧ず鏈勾搴︼紙鏈勾搴︽棤璁″垝鏃堕��鍥炴渶鏂板勾浠斤級
     loadYearOptions() {
-      pageDeviceExaminePlan({
-        current: 1,
-        size: 99,
-      }).then(res => {
-        let years = []
-        if (res.code == 200) {
-          years = (res.data.records || []).map(r => r.planYear).filter(Boolean)
-        }
-        const options = [...new Set(years)].sort((a, b) => b.localeCompare(a))
-        this.yearOptions = options
+      const currentYear = String(new Date().getFullYear())
+      const finish = (years) => {
+        let options = [...new Set((years || []).map(y => String(y)).filter(Boolean))]
+        options.sort((a, b) => b.localeCompare(a))
         if (options.length === 0) {
-          this.planYear = ''
-          this.planInfo = {}
-          this.yearTableDetailData = []
-          this.pagination1.total = 0
-          return
+          options = [currentYear]
         }
-        if (options.indexOf(this.planYear) === -1) {
-          const currentYear = String(new Date().getFullYear())
-          this.planYear = options.indexOf(currentYear) > -1 ? currentYear : options[0]
-        }
+        this.yearOptions = options
+        const keep = options.indexOf(String(this.planYear)) > -1
+        this.planYear = keep ? String(this.planYear) : (options.includes(currentYear) ? currentYear : options[0])
         this.loadPlan()
+      }
+      getExaminePlanYears().then(res => {
+        finish(res.code == 200 ? (res.data || []) : [])
+      }).catch(() => {
+        finish([])
       })
     },
     // 鍒囨崲骞翠唤
@@ -504,7 +501,7 @@
     },
     // 鏄庣粏-鍒犻櫎
     deleteFun1(id) {
-      this.$confirm('鍒犻櫎鍚庯紝璇ヨ鏈鏍哥殑鏍告煡璁板綍鍙婇檮浠朵細涓�骞跺垹闄わ紱鑻ヨ璁惧杩樻湁瀹℃牳閫氳繃鐨勬牳鏌ヨ褰曪紝妗f鐨勬渶杩戞牳鏌ユ棩鏈熷皢鍥為��鍒版渶杩戜竴娆″畬鎴愯褰曪紱鑻ユ病鏈夛紝鍒欐竻绌烘。妗堢殑鏍告煡鏃ユ湡鍜屾牳鏌ュ懆鏈熴�傛槸鍚︾户缁�?', '鎻愮ず', {
+      this.$confirm('鍒犻櫎鍚庯紝璇ヨ鐨勬牳鏌ヨ褰曪紙鏈鏍告垨瀹℃牳涓嶉�氳繃锛夊強闄勪欢浼氫竴骞跺垹闄わ紱鑻ヨ璁惧杩樻湁瀹℃牳閫氳繃鐨勬牳鏌ヨ褰曪紝妗f鐨勬渶杩戞牳鏌ユ棩鏈熷皢鍥為��鍒版渶杩戜竴娆″畬鎴愯褰曪紱鑻ユ病鏈夛紝鍒欐竻绌烘。妗堢殑鏍告煡鏃ユ湡鍜屾牳鏌ュ懆鏈熴�傛槸鍚︾户缁�?', '鎻愮ず', {
         confirmButtonText: '纭畾',
         cancelButtonText: '鍙栨秷',
         type: 'warning'
@@ -520,10 +517,15 @@
         });
       });
     },
-    // 瀵煎嚭骞村害璁″垝琛�
+    // 瀵煎嚭骞村害璁″垝琛紙Excel锛夛細鏈夌瓫閫夋潯浠跺鍑虹瓫閫夌粨鏋滐紝娌℃湁绛涢�夊鍑鸿骞翠唤鍏ㄩ儴
     downLoadPost() {
-      exportDeviceExaminePlanDetail({ planId: this.planInfo.planId }).then(res => {
-        this.saveDocx(res, '浠櫒璁惧鏈熼棿鏍告煡璁″垝琛�.docx')
+      exportDeviceExaminePlanDetail({
+        planId: this.planInfo.planId,
+        deviceName: this.searchForm.deviceName,
+        deviceNumber: this.searchForm.deviceNumber,
+      }).then(res => {
+        const planName = this.planInfo.planName || (this.planYear ? this.planYear + '骞村害璁惧鏍告煡璁″垝' : '璁惧鏍告煡璁″垝')
+        this.saveDocx(res, planName + '.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
       }).catch(() => { })
     },
     // 鏈鏄惁鏈夋敼鍔紙鍚墦寮�鏃舵仮澶嶇殑鑽夌锛�
@@ -586,7 +588,7 @@
       this.downloadDialog = true
     },
     // 瀵煎嚭缁撴灉鎷︽埅: 鍚庣杩斿洖閿欒 JSON 鏃舵彁绀洪敊璇�, 涓嶅瓨鎴愬潖鏂囦欢
-    saveDocx(res, filename) {
+    saveDocx(res, filename, mime = 'application/msword') {
       const reader = new FileReader();
       reader.readAsText(res, 'utf-8');
       reader.onload = () => {
@@ -596,11 +598,11 @@
           try { msg = JSON.parse(text).msg || msg; } catch (e) { }
           this.$message.error(msg);
         } else {
-          this.$download.saveAs(new Blob([res], { type: 'application/msword' }), filename);
+          this.$download.saveAs(new Blob([res], { type: mime }), filename);
         }
       };
       reader.onerror = () => {
-        this.$download.saveAs(new Blob([res], { type: 'application/msword' }), filename);
+        this.$download.saveAs(new Blob([res], { type: mime }), filename);
       };
     },
     // 鏍告煡璁板綍瀵煎嚭
diff --git a/src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue b/src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue
index daac854..6ba22b3 100644
--- a/src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue
+++ b/src/views/CNAS/resourceDemand/device/component/usageAuthorization.vue
@@ -90,7 +90,7 @@
         <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="storagePoint" label="褰掑睘瀹為獙瀹�"></el-table-column>
+        <el-table-column prop="storagePoint" label="瀛樻斁鐐�"></el-table-column>
       </el-table>
       <template #footer><span  class="dialog-footer">
         <el-button @click="addEquipDia = false">鍙� 娑�</el-button>
diff --git a/src/views/CNAS/systemManagement/customerSatisfaction/components/formDialog.vue b/src/views/CNAS/systemManagement/customerSatisfaction/components/formDialog.vue
index 8ad497f..b128c19 100644
--- a/src/views/CNAS/systemManagement/customerSatisfaction/components/formDialog.vue
+++ b/src/views/CNAS/systemManagement/customerSatisfaction/components/formDialog.vue
@@ -136,6 +136,17 @@
             </el-input>
           </td>
         </tr>
+        <tr>
+          <td class="td-title">
+            <p>鐓х墖锛�</p>
+          </td>
+          <td class="td-info" colspan="5">
+            <lims-attachment ref="photoAttachment" inline defer-upload accept=".jpg,.jpeg,.png,.gif"
+              :main-id="form.clientSatisfactionId || ''" upload-url="/clientSatisfaction/uploadAttachment"
+              select-url="/clientSatisfaction/selectAttachments" delete-url="/clientSatisfaction/deleteAttachment"
+              id-param="clientSatisfactionId" tip="鏀寔 jpg / png / gif 鐓х墖锛屽彲棰勮锛屾彁浜ゆ椂涓�骞朵笂浼�"></lims-attachment>
+          </td>
+        </tr>
       </table>
       <template #footer><span  class="dialog-footer">
         <el-button @click="closeFormDia">鍙� 娑�</el-button>
@@ -151,10 +162,11 @@
   updateClientSatisfaction
 } from '@/api/cnas/systemManagement/customerSatisfaction.js'
 import { selectCompletedOrders } from '@/api/business/productOrder'
+import limsAttachment from '@/components/Attachment/lims-attachment.vue'
 export default {
   name: 'formDialog',
   // import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
-  components: {},
+  components: { limsAttachment },
   data() {
     // 杩欓噷瀛樻斁鏁版嵁
     return {
@@ -287,24 +299,45 @@
       }
       if (this.operationType === 'add') {
         addClientSatisfaction(payload).then(res => {
-          this.editLoad = false
-          this.$message.success('鎻愪氦鎴愬姛')
-          this.closeFormDia()
+          // 鍚庣杩斿洖淇濆瓨鍚庣殑璁板綍锛堝惈鑷id锛夛紝鐢ㄤ簬鎶婃柊澧炴椂鏆傚瓨鐨勭収鐗囦紶涓婂幓
+          const savedId = res.data && res.data.clientSatisfactionId
+          this.finishSave(savedId)
         }).catch(err => {
           console.log('err---', err);
           this.editLoad = false
         })
       } else {
-        updateClientSatisfaction(payload).then(res => {
-          this.editLoad = false
-          this.$message.success('鎻愪氦鎴愬姛')
-          this.closeFormDia()
+        updateClientSatisfaction(payload).then(() => {
+          this.finishSave(this.form.clientSatisfactionId)
         }).catch(err => {
           console.log('err---', err);
           this.editLoad = false
         })
       }
     },
+    // 璁板綍淇濆瓨鎴愬姛鍚庝笂浼犳殏瀛樼収鐗囷紱鐓х墖涓婁紶澶辫触涓嶅奖鍝嶈褰曟湰韬�
+    finishSave(clientSatisfactionId) {
+      this.uploadPendingPhotos(clientSatisfactionId).then(() => {
+        this.editLoad = false
+        this.$message.success('鎻愪氦鎴愬姛')
+        this.closeFormDia()
+      }).catch(err => {
+        console.log('鐓х墖涓婁紶澶辫触', err)
+        this.editLoad = false
+        this.$message.warning('璁板綍宸蹭繚瀛橈紝浣嗙収鐗囦笂浼犲け璐ワ紝璇峰洖鍒板垪琛ㄧ敤鈥滈檮浠垛�濊ˉ鍏呬笂浼�')
+        this.closeFormDia()
+      })
+    },
+    uploadPendingPhotos(clientSatisfactionId) {
+      const attachment = this.$refs.photoAttachment
+      if (!attachment || !attachment.pendingFiles.length) {
+        return Promise.resolve()
+      }
+      if (!clientSatisfactionId) {
+        return Promise.reject(new Error('鏈幏鍙栧埌璁板綍id锛屾棤娉曚笂浼犵収鐗�'))
+      }
+      return attachment.flushPending(clientSatisfactionId)
+    },
     closeFormDia() {
       this.formDia = false;
       this.$emit('closeFormDia')

--
Gitblit v1.9.3