From d2eed0eb7c2f9537d5eaab7ccc3b6ab258959227 Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期六, 24 十月 2026 20:48:11 +0800
Subject: [PATCH] feat(device): 设备核查计划附件上传与运行记录导出调整

---
 src/views/CNAS/resourceDemand/device/component/checkRecord.vue |  317 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 218 insertions(+), 99 deletions(-)

diff --git a/src/views/CNAS/resourceDemand/device/component/checkRecord.vue b/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
index d2ab78a..214d943 100644
--- a/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
+++ b/src/views/CNAS/resourceDemand/device/component/checkRecord.vue
@@ -1,61 +1,125 @@
 <template>
   <div>
     <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="dialogVisible"
-      :title="currentStep === 0 ? '鏂板鏍告煡璁板綍' : '璁惧鏍告煡璁板綍'" width="50%" @close="resetForm">
-      <el-steps v-if="currentStep === 1" :active="1" align-center finish-status="success">
+      :title="currentStep === 0 ? '鏂板鏍告煡璁板綍' : '璁惧鏍告煡璁板綍'" top="5vh" width="960px" @close="resetForm">
+      <el-steps v-if="currentStep === 1" class="record-steps" :active="1" align-center finish-status="success">
         <el-step title="濉啓鏍告煡璁板綍"></el-step>
         <el-step title="瀹℃牳"></el-step>
       </el-steps>
-      <el-form ref="recordForm" :model="form" :rules="rules" label-width="110px">
-        <el-form-item label="璁惧缂栧彿锛�" prop="deviceNumber">
-          <el-input v-model="form.deviceNumber" disabled size="small"></el-input>
-        </el-form-item>
-        <el-form-item label="璁惧鍚嶇О锛�" prop="deviceName">
-          <el-select v-if="currentStep === 0" v-model="selectedDeviceId" clearable filterable
-            placeholder="璇烽�夋嫨璁惧" size="small" style="width: 100%" @change="changeMachineName">
-            <el-option v-for="item in equipOptions" :key="item.id" :label="item.label + '-' + item.value"
-              :value="item.id"></el-option>
-          </el-select>
-          <el-input v-else v-model="form.deviceName" disabled size="small"></el-input>
-        </el-form-item>
-        <el-form-item label="鏍告煡鏃堕棿锛�" prop="checkTime">
-          <el-date-picker v-model="form.checkTime" :disabled="currentStep !== 0" clearable format="YYYY-MM"
-            placeholder="閫夋嫨鏃ユ湡" size="small" style="width: 100%" type="month" value-format="YYYY-MM">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="鏍告煡鎸囨爣锛�" prop="checkIndex">
-          <el-input v-model="form.checkIndex" :disabled="currentStep !== 0" clearable size="small"></el-input>
-        </el-form-item>
-        <el-form-item label="鏍告煡鏂规硶锛�" prop="checkMethod">
-          <el-input v-model="form.checkMethod" :disabled="currentStep !== 0" clearable size="small"
-            type="textarea"></el-input>
-        </el-form-item>
-        <el-form-item label="缁撴灉濡備綍鍒ゅ畾锛�" prop="howResults">
-          <el-input v-model="form.howResults" :disabled="currentStep !== 0" clearable size="small"
-            type="textarea"></el-input>
-        </el-form-item>
-        <el-form-item label="鏍告煡璐d换浜猴細" prop="checkChargerUserId">
-          <el-select v-if="currentStep === 0" v-model="form.checkChargerUserId" clearable filterable
-            placeholder="璇烽�夋嫨" size="small" style="width: 100%" @change="setCheckChargerUser">
-            <el-option v-for="item in chargerOptions" :key="item.id" :label="item.name"
-              :value="item.id"></el-option>
-          </el-select>
-          <el-input v-else v-model="form.checkChargerUser" disabled size="small"></el-input>
-        </el-form-item>
-        <el-form-item label="澶囨敞锛�" prop="remark">
-          <el-input v-model="form.remark" :disabled="currentStep !== 0" clearable size="small"></el-input>
-        </el-form-item>
-        <el-form-item label="闄勪欢锛�">
-          <el-upload v-if="currentStep === 0" :action="javaApi + '/deviceScope/uploadFile'" :headers="uploadHeader"
-            :limit="1" :on-exceed="handleUploadExceed" :before-upload="beforeAttachmentUpload"
-            :on-success="handleAttachmentSuccess" :on-remove="handleAttachmentRemove">
-            <el-button size="small" type="primary">閫夋嫨闄勪欢</el-button>
-          </el-upload>
-          <el-link v-if="form.fileUrl" type="primary" @click="openAttachment">
-            {{ form.fileName || '鏌ョ湅闄勪欢' }}
-          </el-link>
-          <span v-else-if="currentStep !== 0">鈥�</span>
-        </el-form-item>
+      <el-form ref="recordForm" :model="form" :rules="rules" label-width="104px">
+        <div class="form-section">
+          <div class="form-section-title">鍩烘湰淇℃伅</div>
+          <el-row :gutter="12">
+            <el-col :span="12">
+              <el-form-item label="浠櫒鍚嶇О锛�" prop="deviceName">
+                <el-select v-if="currentStep === 0" v-model="selectedDeviceId" clearable filterable
+                  placeholder="璇烽�夋嫨璁惧" size="small" style="width: 100%" @change="changeMachineName">
+                  <el-option v-for="item in equipOptions" :key="item.id" :label="item.label + '-' + item.value"
+                    :value="item.id"></el-option>
+                </el-select>
+                <el-input v-else v-model="form.deviceName" disabled size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="妫�鏌ユ棩鏈燂細" prop="checkTime">
+                <el-date-picker v-if="currentStep === 0" v-model="form.checkTime" clearable format="YYYY-MM-DD"
+                  placeholder="閫夋嫨妫�鏌ユ棩鏈�" size="small" style="width: 100%" type="date" value-format="YYYY-MM-DD"
+                  @change="resolveAttachmentPlan">
+                </el-date-picker>
+                <el-input v-else v-model="form.checkTime" disabled size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="绠$悊缂栧彿锛�" prop="deviceNumber">
+                <el-input v-model="form.deviceNumber" disabled size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="璁惧鍨嬪彿锛�" prop="deviceModel">
+                <el-input v-model="form.deviceModel" disabled size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="鏍告煡浜猴細" prop="checkChargerUserId">
+                <el-select v-if="currentStep === 0" v-model="form.checkChargerUserId" clearable filterable
+                  placeholder="璇烽�夋嫨" size="small" style="width: 100%" @change="setCheckChargerUser">
+                  <el-option v-for="item in chargerOptions" :key="item.id" :label="item.name"
+                    :value="item.id"></el-option>
+                </el-select>
+                <el-input v-else v-model="form.checkChargerUser" disabled size="small"></el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+        <div class="form-section">
+          <div class="form-section-title">鏍告煡鍐呭</div>
+          <el-row :gutter="12">
+            <el-col :span="8">
+              <el-form-item label="鐜娓╂箍搴︼細" prop="environment">
+                <el-input v-model="form.environment" :disabled="currentStep !== 0" clearable size="small"
+                  placeholder="濡傦細25鈩� / 50%RH"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="鏍告煡渚濇嵁锛�" prop="checkBasis">
+                <el-input v-model="form.checkBasis" :disabled="currentStep !== 0" clearable size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="鏍告煡鎸囨爣锛�" prop="checkIndex">
+                <el-input v-model="form.checkIndex" :disabled="currentStep !== 0" clearable size="small"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="鏍告煡鏂瑰紡锛�" prop="checkMethod">
+                <el-input v-model="form.checkMethod" :disabled="currentStep !== 0" clearable :rows="2" size="small"
+                  type="textarea"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="缁撴灉濡備綍鍒ゅ畾锛�" prop="howResults">
+                <el-input v-model="form.howResults" :disabled="currentStep !== 0" clearable :rows="2" size="small"
+                  type="textarea"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="澶栬鎯呭喌锛�">
+                <el-radio-group v-model="form.appearanceStatus" :disabled="currentStep !== 0">
+                  <el-radio value="鑹ソ">鑹ソ</el-radio>
+                  <el-radio value="涓�鑸�">涓�鑸�</el-radio>
+                  <el-radio value="鎹熷潖">鎹熷潖</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="杩愯鐘舵�侊細">
+                <el-radio-group v-model="form.runningStatus" :disabled="currentStep !== 0">
+                  <el-radio value="姝e父">姝e父</el-radio>
+                  <el-radio value="寮傚父">寮傚父</el-radio>
+                  <el-radio value="鍋滄満">鍋滄満</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="澶囨敞锛�" prop="remark">
+                <el-input v-model="form.remark" :disabled="currentStep !== 0" clearable size="small"></el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </div>
+        <div class="form-section">
+          <div class="form-section-title">闄勪欢璧勬枡</div>
+          <el-form-item label-width="0">
+            <lims-attachment ref="recordAttachment" inline upload-url="/deviceExaminePlan/uploadAttachment"
+              select-url="/deviceExaminePlan/selectAttachments" delete-url="/deviceExaminePlan/deleteAttachment"
+              id-param="planDetailsId" name-field="deviceName" title="鏍告煡璁板綍闄勪欢"
+              :main-id="form.planDetailsId" :readonly="currentStep === 1"
+              :defer-upload="currentStep === 0" :tip="attachmentTip"></lims-attachment>
+            <el-link v-if="form.fileUrl" type="primary" @click="openAttachment">
+              {{ form.fileName || '鏌ョ湅鍘熼檮浠�' }}
+            </el-link>
+          </el-form-item>
+        </div>
       </el-form>
       <template #footer><span class="dialog-footer">
         <el-button @click="resetForm">鍙� 娑�</el-button>
@@ -74,22 +138,28 @@
   addExamineRecord,
   reviewExamineRecord,
   deviceScopeSearch,
+  findExaminePlanDetail,
   resolveExaminePlanDetail,
   updateDeviceExaminePlanDetail,
 } from '@/api/cnas/resourceDemand/device.js'
 import { selectUserCondition } from "@/api/performance/class";
-import draftSave from '@/mixins/draftSave'
+import LimsAttachment from '@/components/Attachment/lims-attachment.vue'
 
 const createEmptyForm = () => ({
   deviceId: '',
   deviceName: '',
   deviceNumber: '',
+  deviceModel: '',
   checkTime: '',
   checkIndex: '',
   checkMethod: '',
   howResults: '',
   checkChargerUserId: '',
   checkChargerUser: '',
+  environment: '',
+  checkBasis: '',
+  appearanceStatus: '',
+  runningStatus: '',
   remark: '',
   fileName: '',
   fileUrl: '',
@@ -97,7 +167,7 @@
 })
 export default {
   name: "check-record",
-  mixins: [draftSave],
+  components: { LimsAttachment },
   data() {
     // 杩欓噷瀛樻斁鏁版嵁
     return {
@@ -109,7 +179,7 @@
       submitFormLoading: false,
       userList: [],
       rules: {
-        checkMethod: [{ required: true, message: '璇峰~鍐欐牳鏌ユ柟娉�', trigger: 'blur' }],
+        checkMethod: [{ required: true, message: '璇峰~鍐欐牳鏌ユ柟寮�', trigger: 'blur' }],
       },
     }
   },
@@ -124,12 +194,17 @@
         deviceId: row.deviceId || '',
         deviceName: row.deviceName || '',
         deviceNumber: row.deviceNumber || '',
-        checkTime: (row.checkTime || '').substring(0, 7),
+        deviceModel: row.deviceModel || '',
+        checkTime: row.checkTime || '',
         checkIndex: row.checkIndex || '',
         checkMethod: row.checkMethod || '',
         howResults: row.howResults || '',
         checkChargerUserId: row.checkChargerUserId || '',
         checkChargerUser: row.checkChargerUser || '',
+        environment: row.environment || '',
+        checkBasis: row.checkBasis || '',
+        appearanceStatus: row.appearanceStatus || '',
+        runningStatus: row.runningStatus || '',
         remark: row.remark || '',
         fileName: row.fileName || '',
         fileUrl: row.fileUrl || '',
@@ -143,17 +218,14 @@
       this.form = createEmptyForm()
       this.selectedDeviceId = ''
       const now = new Date()
-      this.form.checkTime = now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0')
+      this.form.checkTime = now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0')
       this.getEquipOptions()
       this.getUserList()
       this.$nextTick(() => {
         if (this.$refs.recordForm) {
           this.$refs.recordForm.clearValidate()
         }
-        this.draftRestore('checkRecordForm', 'form', 'new', 'dialogVisible')
-        if (this.form.deviceId) {
-          this.selectedDeviceId = this.form.deviceId
-        }
+        this.resolveAttachmentPlan()
       })
     },
     // 鎸夎澶� id 鍥炲~鍚嶇О鍜岀紪鍙凤紝閬垮厤鍚屽悕璁惧閫夐敊
@@ -163,11 +235,14 @@
         this.form.deviceId = item.id
         this.form.deviceName = item.deviceName
         this.form.deviceNumber = item.managementNumber
+        this.form.deviceModel = item.specificationModel || ''
       } else {
         this.form.deviceId = ''
         this.form.deviceName = ''
         this.form.deviceNumber = ''
+        this.form.deviceModel = ''
       }
+      this.resolveAttachmentPlan()
     },
     setCheckChargerUser(value) {
       const item = this.userList.find(user => user.id === value)
@@ -214,28 +289,40 @@
       if (this.form.howResults) params.howResults = this.form.howResults
       if (this.form.checkChargerUserId) params.checkChargerUserId = this.form.checkChargerUserId
       if (this.form.checkChargerUser) params.checkChargerUser = this.form.checkChargerUser
+      if (this.form.deviceModel) params.deviceModel = this.form.deviceModel
+      params.environment = this.form.environment || ''
+      params.checkBasis = this.form.checkBasis || ''
+      params.appearanceStatus = this.form.appearanceStatus || ''
+      params.runningStatus = this.form.runningStatus || ''
       if (this.form.remark) params.remark = this.form.remark
       if (this.form.fileName) params.fileName = this.form.fileName
       if (this.form.fileUrl) params.fileUrl = this.form.fileUrl
-      updateDeviceExaminePlanDetail(params).then(res => {
-        if (res.code !== 200) {
-          this.$message.error(res.msg || '淇濆瓨鏍告煡璁板綍澶辫触')
-          this.submitFormLoading = false
-          return
-        }
-        addExamineRecord({ planDetailsId }).then(recordRes => {
-          if (recordRes.code == 200) {
-            this.$message.success('鏍告煡璁板綍宸叉彁浜わ紝绛夊緟瀹℃牳')
-            this.draftClear('checkRecordForm')
-            this.resetForm()
-          } else {
-            this.$message.error(recordRes.msg || '鎻愪氦鏍告煡璁板綍澶辫触')
+      // 闄勪欢鍏堟殏瀛樺湪椤甸潰涓婏紝纭鎻愪氦鏃跺啀杩炲悓鏍告煡璁板綍涓�璧蜂繚瀛橈紝鍙栨秷鍒欎粈涔堥兘涓嶇暀
+      const attachmentRef = this.$refs.recordAttachment
+      const flushPending = attachmentRef ? attachmentRef.flushPending(planDetailsId) : Promise.resolve()
+      flushPending.then(() => {
+        updateDeviceExaminePlanDetail(params).then(res => {
+          if (res.code !== 200) {
+            this.$message.error(res.msg || '淇濆瓨鏍告煡璁板綍澶辫触')
+            this.submitFormLoading = false
+            return
           }
-          this.submitFormLoading = false
+          addExamineRecord({ planDetailsId }).then(recordRes => {
+            if (recordRes.code == 200) {
+              this.$message.success('鏍告煡璁板綍宸叉彁浜わ紝绛夊緟瀹℃牳')
+              this.resetForm()
+            } else {
+              this.$message.error(recordRes.msg || '鎻愪氦鏍告煡璁板綍澶辫触')
+            }
+            this.submitFormLoading = false
+          }).catch(() => {
+            this.submitFormLoading = false
+          })
         }).catch(() => {
           this.submitFormLoading = false
         })
       }).catch(() => {
+        // 涓婁紶澶辫触鐨勫叿浣撳師鍥犵敱 request 鎷︽埅鍣ㄧ粺涓�鎻愮ず
         this.submitFormLoading = false
       })
     },
@@ -249,7 +336,6 @@
       reviewExamineRecord(params).then(res => {
         if (res.code == 200) {
           this.$message.success(statue === 1 ? '瀹℃牳閫氳繃' : '宸查��鍥�')
-          this.draftClear('checkRecordForm')
           this.resetForm()
         }
         this.submitFormLoading = false
@@ -258,7 +344,6 @@
       })
     },
     resetForm() {
-      this.draftStop('checkRecordForm')
       this.dialogVisible = false
       this.$emit('closeDialog1')
     },
@@ -283,30 +368,27 @@
         this.userList = res.data
       })
     },
-    // 闄勪欢
-    beforeAttachmentUpload(file) {
-      if (file.size > 1024 * 1024 * 10) {
-        this.$message.error('涓婁紶鏂囦欢涓嶈秴杩�10M')
-        return false
+    // 闄勪欢鍐呭祵鍦ㄨ〃鍗曢噷锛氳澶�+鏃ユ湡纭畾鍚庡彧鏌ュ彲澶嶇敤鏄庣粏锛屼笉鎻愬墠寤烘。锛岄伩鍏嶅彇娑堝悗鐣欎笅绌鸿褰�
+    resolveAttachmentPlan() {
+      if (this.currentStep !== 0 || !this.selectedDeviceId || !this.form.checkTime) {
+        this.form.planDetailsId = ''
+        return
       }
-      return true
+      const deviceId = this.selectedDeviceId
+      const checkTime = this.form.checkTime
+      this.form.planDetailsId = ''
+      findExaminePlanDetail({ deviceId, checkTime }).then(res => {
+        if (res.code !== 200 || !res.data) {
+          return
+        }
+        // 璇锋眰鏈熼棿鐢ㄦ埛鍙兘宸插垏鎹㈣澶囨垨鏃ユ湡锛岄伩鍏嶅洖濉繃鏈熸槑缁�
+        if (this.selectedDeviceId === deviceId && this.form.checkTime === checkTime) {
+          this.form.planDetailsId = res.data.planDetailsId
+        }
+      }).catch(() => {
+      })
     },
-    handleUploadExceed() {
-      this.$message.warning('浠呮敮鎸佷竴涓檮浠讹紝璇峰厛绉婚櫎宸蹭笂浼犵殑闄勪欢')
-    },
-    handleAttachmentSuccess(response) {
-      if (response.code == 200) {
-        this.form.fileName = response.data.name
-        this.form.fileUrl = response.data.url
-        this.$message.success('闄勪欢涓婁紶鎴愬姛')
-      } else {
-        this.$message.error(response.msg || '闄勪欢涓婁紶澶辫触')
-      }
-    },
-    handleAttachmentRemove() {
-      this.form.fileName = ''
-      this.form.fileUrl = ''
-    },
+    // 鍏煎鍘嗗彶鍗曢檮浠�
     openAttachment() {
       if (!this.form.fileUrl) {
         return
@@ -316,6 +398,10 @@
     },
   },
   computed: {
+    // 闄勪欢涓嶆彁鍓嶄笂浼狅紝閫夊ソ鍚庨殢鏍告煡璁板綍涓�璧锋彁浜や繚瀛�
+    attachmentTip() {
+      return '鍙洿鎺ラ�夋嫨闄勪欢锛岀偣鈥滅‘璁も�濇椂闅忔牳鏌ヨ褰曚竴璧蜂繚瀛�'
+    },
     // 璐d换浜轰笅鎷夛細宸蹭繚瀛樼殑璐d换浜轰笉鍦ㄥ�欓�夊垪琛ㄦ椂琛ヤ竴鏉★紝閬垮厤鍥炴樉鎴愮敤鎴稩D
     chargerOptions() {
       const list = this.userList || []
@@ -328,3 +414,36 @@
   },
 }
 </script>
+
+<style scoped>
+.record-steps {
+  margin-bottom: 14px;
+}
+
+.form-section {
+  padding: 12px 14px 0;
+  border: 1px solid #ebeef5;
+  border-radius: 6px;
+  margin-bottom: 10px;
+}
+
+.form-section:last-child {
+  margin-bottom: 0;
+}
+
+.form-section-title {
+  display: flex;
+  align-items: center;
+  padding-left: 8px;
+  border-left: 3px solid var(--el-color-primary);
+  margin-bottom: 12px;
+  font-size: 14px;
+  font-weight: 600;
+  line-height: 1;
+  color: #303133;
+}
+
+.form-section :deep(.el-form-item) {
+  margin-bottom: 12px;
+}
+</style>

--
Gitblit v1.9.3