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/components/Attachment/lims-attachment.vue |  141 +++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 135 insertions(+), 6 deletions(-)

diff --git a/src/components/Attachment/lims-attachment.vue b/src/components/Attachment/lims-attachment.vue
index e99027c..62ae50d 100644
--- a/src/components/Attachment/lims-attachment.vue
+++ b/src/components/Attachment/lims-attachment.vue
@@ -1,10 +1,39 @@
 <template>
-  <div>
-    <el-dialog :title="dialogTitle" v-model="visible" width="760px">
+  <div class="lims-attachment">
+    <div v-if="inline" class="attachment-inline">
       <div class="attachment-header">
-        <div class="el-upload__tip">{{ tip }}</div>
-        <el-upload :action="uploadAction" :headers="uploadHeader" multiple :show-file-list="false"
-          :on-success="handleUploadSuccess" :on-error="handleUploadError">
+        <div class="el-upload__tip">
+          {{ readonly ? '浠呭彲棰勮銆佷笅杞介檮浠�' : ((currentId || deferUpload) ? tip : emptyTip) }}
+        </div>
+        <el-upload v-if="!readonly" :action="uploadAction" :headers="uploadHeader" multiple
+          :show-file-list="false" :disabled="!canUpload" :auto-upload="!deferUpload"
+          :on-change="handleFileChange" :on-success="handleUploadSuccess"
+          :on-error="handleUploadError">
+          <el-button size="small" type="primary" :disabled="!canUpload">涓婁紶闄勪欢</el-button>
+        </el-upload>
+      </div>
+      <el-table :data="displayList" border size="small" max-height="180" style="margin-top:8px">
+        <el-table-column label="鏂囦欢鍚嶇О" prop="fileName" min-width="220" show-overflow-tooltip />
+        <el-table-column label="涓婁紶鏃堕棿" prop="createTime" width="160" />
+        <el-table-column label="鎿嶄綔" width="170">
+          <template #default="scope">
+            <template v-if="scope.row.pending">
+              <el-button link type="danger" @click="removePending(scope.row)">鍒犻櫎</el-button>
+            </template>
+            <template v-else>
+              <el-button link type="primary" @click="previewFile(scope.row)">棰勮</el-button>
+              <el-button link type="primary" @click="downloadFile(scope.row)">涓嬭浇</el-button>
+              <el-button v-if="!readonly" link type="danger" @click="removeFile(scope.row)">鍒犻櫎</el-button>
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <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
+          :show-file-list="false" :on-success="handleUploadSuccess" :on-error="handleUploadError">
           <el-button size="small" type="primary">涓婁紶闄勪欢</el-button>
         </el-upload>
       </div>
@@ -15,7 +44,7 @@
           <template #default="scope">
             <el-button link type="primary" @click="previewFile(scope.row)">棰勮</el-button>
             <el-button link type="primary" @click="downloadFile(scope.row)">涓嬭浇</el-button>
-            <el-button link type="danger" @click="removeFile(scope.row)">鍒犻櫎</el-button>
+            <el-button v-if="!readonly" link type="danger" @click="removeFile(scope.row)">鍒犻櫎</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -51,6 +80,7 @@
   components: {
     filePreview
   },
+  emits: ['closed'],
   props: {
     // 涓婁紶鎺ュ彛鍦板潃锛屽 /supplierManagement/uploadAttachment
     uploadUrl: {
@@ -91,12 +121,54 @@
     tip: {
       type: String,
       default: '鏀寔浠绘剰鏍煎紡鏂囦欢锛屽崟涓枃浠朵笉瓒呰繃200MB'
+    },
+    // 鍙妯″紡锛氫粎棰勮/涓嬭浇锛屼笉鏄剧ず涓婁紶鍜屽垹闄�
+    readonly: {
+      type: Boolean,
+      default: false
+    },
+    // 鍐呭祵妯″紡锛氱洿鎺ユ覆鏌撲笂浼犲尯鍜岄檮浠跺垪琛紝涓嶅脊绠$悊寮圭獥
+    inline: {
+      type: Boolean,
+      default: false
+    },
+    // 鍐呭祵妯″紡鍏宠仈涓昏〃ID锛屽彉鍖栨椂鑷姩鍔犺浇闄勪欢
+    mainId: {
+      type: [String, Number],
+      default: ''
+    },
+    // 鍐呭祵妯″紡鏈叧鑱斾富琛↖D鏃剁殑鎻愮ず
+    emptyTip: {
+      type: String,
+      default: '璇峰厛閫夋嫨鏁版嵁鍚庡啀涓婁紶闄勪欢'
+    },
+    // 鍐呭祵妯″紡锛氭病鏈変富琛↖D鏃朵篃鍏佽閫夋嫨鏂囦欢锛屽厛鏆傚瓨鍦ㄩ〉闈紝鎻愪氦鏃跺啀缁熶竴涓婁紶
+    deferUpload: {
+      type: Boolean,
+      default: false
+    }
+  },
+  watch: {
+    mainId: {
+      immediate: true,
+      handler(val) {
+        if (!this.inline) {
+          return
+        }
+        const field = this.idField || this.idParam
+        this.currentRow = { [field]: val }
+        this.attachmentList = []
+        if (val !== null && val !== undefined && val !== '') {
+          this.loadList()
+        }
+      }
     }
   },
   data() {
     return {
       visible: false,
       attachmentList: [],
+      pendingFiles: [],
       currentRow: {},
       previewVisible: false,
       previewRow: {},
@@ -107,6 +179,19 @@
     currentId() {
       const field = this.idField || this.idParam
       return this.currentRow ? this.currentRow[field] : undefined
+    },
+    canUpload() {
+      return !this.readonly && (!!this.currentId || this.deferUpload)
+    },
+    displayList() {
+      const pending = this.pendingFiles.map(item => ({
+        id: 'pending_' + item.uid,
+        uid: item.uid,
+        fileName: item.fileName,
+        createTime: '寰呬笂浼�',
+        pending: true
+      }))
+      return pending.concat(this.attachmentList)
     },
     dialogTitle() {
       const name = this.nameField && this.currentRow ? this.currentRow[this.nameField] : ''
@@ -171,6 +256,42 @@
     handleUploadError() {
       this.$message.error('涓婁紶澶辫触锛屾枃浠跺彲鑳借秴杩�200MB')
     },
+    // 寤惰繜涓婁紶妯″紡锛氭枃浠跺厛鏆傚瓨鍦ㄩ〉闈紝鎻愪氦淇濆瓨鏃跺啀缁熶竴涓婁紶
+    handleFileChange(file) {
+      if (!this.deferUpload || !file || !file.raw) {
+        return
+      }
+      this.pendingFiles.push({ uid: file.uid, fileName: file.name, raw: file.raw })
+    },
+    removePending(row) {
+      this.pendingFiles = this.pendingFiles.filter(item => item.uid !== row.uid)
+    },
+    // 鎻愪氦鏃惰皟鐢細鎶婃殏瀛樼殑闄勪欢涓婁紶鍒版寚瀹氫富琛↖D锛屽叏閮ㄦ垚鍔熸墠绠楀畬鎴�
+    flushPending(planDetailsId) {
+      if (!this.pendingFiles.length) {
+        return Promise.resolve()
+      }
+      const field = this.idField || this.idParam
+      this.currentRow = { [field]: planDetailsId }
+      return Promise.all(this.pendingFiles.slice().map(item => {
+        const formData = new FormData()
+        formData.append('file', item.raw)
+        return request({
+          url: this.uploadUrl,
+          method: 'post',
+          params: { [this.idParam]: planDetailsId },
+          data: formData,
+          headers: { 'Content-Type': 'multipart/form-data', repeatSubmit: false }
+        }).then(res => {
+          if (!res || res.code !== 200) {
+            throw new Error((res && res.msg) || ('闄勪欢鈥�' + item.fileName + '鈥濅笂浼犲け璐�'))
+          }
+          this.pendingFiles = this.pendingFiles.filter(pending => pending.uid !== item.uid)
+        })
+      })).then(() => {
+        this.loadList()
+      })
+    },
     previewFile(row) {
       this.previewRow = row
       this.previewUrl = this.fullUrl(row.fileUrl)
@@ -201,9 +322,17 @@
 </script>
 
 <style scoped>
+.lims-attachment {
+  width: 100%;
+}
+
 .attachment-header {
   display: flex;
   justify-content: space-between;
   align-items: center;
 }
+
+.attachment-inline {
+  width: 100%;
+}
 </style>

--
Gitblit v1.9.3