From 0c03027d7f238bf5beb98e85463f53f0bd92bbaa Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期一, 20 四月 2026 17:56:01 +0800
Subject: [PATCH] 青岛维护

---
 src/views/OfficeRelated/conference/index.vue | 1007 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 846 insertions(+), 161 deletions(-)

diff --git a/src/views/OfficeRelated/conference/index.vue b/src/views/OfficeRelated/conference/index.vue
index bc55057..30ec96d 100644
--- a/src/views/OfficeRelated/conference/index.vue
+++ b/src/views/OfficeRelated/conference/index.vue
@@ -128,7 +128,10 @@
           prop="organizerName"
           label="缁勭粐鑰�"
           width="120"
-        />
+          ><template #default="scope">
+            <span>{{ scope.organizerName || scope.createBy }}</span>
+          </template>
+        </el-table-column>
         <el-table-column
           align="center"
           prop="locationName"
@@ -270,35 +273,98 @@
         </div>
 
         <!-- 浼氳绾闄勪欢灞曠ず -->
-        <div
-          class="minutes-attachments"
-          v-if="
-            currentRecord.recordattachment &&
-              parseAttachments(currentRecord.recordattachment).length > 0
-          "
-        >
-          <el-divider content-position="left">浼氳绾闄勪欢</el-divider>
-          <div class="attachment-list">
+        <div class="detail-attachments">
+          <div
+            v-if="parseAttachments(currentRecord.recordattachment).length > 0"
+            class="attachment-grid"
+          >
             <div
               v-for="file in parseAttachments(currentRecord.recordattachment)"
               :key="file.id || file.name"
-              class="attachment-item"
+              class="attachment-card"
             >
-              <el-link
-                type="primary"
-                :href="file.url"
-                target="_blank"
-                class="file-link"
-              >
-                <i
-                  :class="getFileIcon(file.type || file.name)"
-                  style="margin-right: 8px;"
-                ></i>
-                {{ file.name }}
-                <span class="file-size" v-if="file.size"
-                  >({{ formatFileSize(file.size) }})</span
+              <template v-if="isImageFile(file)">
+                <!-- 鍥剧墖浣跨敤 el-image 棰勮 -->
+                <el-image
+                  class="image-attachment"
+                  :src="getFileUrl(file)"
+                  :preview-src-list="getImagePreviewList(file)"
+                  fit="cover"
+                  :style="{ width: imageSize, height: imageSize }"
+                  lazy
                 >
-              </el-link>
+                  <div slot="error" class="image-error">
+                    <i class="el-icon-picture-outline"></i>
+                    <span>鍔犺浇澶辫触</span>
+                  </div>
+                  <div slot="placeholder" class="image-loading">
+                    <i class="el-icon-loading"></i>
+                  </div>
+                </el-image>
+                <div class="image-info">
+                  <div class="file-name" :title="file.name">
+                    {{ file.name }}
+                  </div>
+                  <div class="file-actions">
+                    <el-button
+                      type="text"
+                      size="mini"
+                      @click="handleDownload(file)"
+                      icon="el-icon-download"
+                      title="涓嬭浇"
+                    />
+                    <el-button
+                      type="text"
+                      size="mini"
+                      @click="handlePreview(file)"
+                      icon="el-icon-view"
+                      title="棰勮"
+                    />
+                  </div>
+                </div>
+              </template>
+
+              <template v-else>
+                <!-- 闈炲浘鐗囨枃浠朵繚鎸佸師鏈夋牱寮� -->
+                <el-card shadow="hover" class="file-card">
+                  <div class="file-content">
+                    <i
+                      :class="getFileIcon(file.type || file.name)"
+                      class="file-icon"
+                    ></i>
+                    <div class="file-info">
+                      <div class="file-name" :title="file.name">
+                        {{ file.name }}
+                      </div>
+                      <div class="file-meta">
+                        <span class="file-type">{{
+                          getFileTypeText(file)
+                        }}</span>
+                        <span class="file-size" v-if="file.size">
+                          {{ formatFileSize(file.size) }}
+                        </span>
+                      </div>
+                    </div>
+                  </div>
+                  <div class="file-actions" v-if="file.url">
+                    <el-button
+                      type="text"
+                      size="mini"
+                      @click="handleDownload(file)"
+                    >
+                      涓嬭浇
+                    </el-button>
+                    <el-button
+                      v-if="canPreview(file)"
+                      type="text"
+                      size="mini"
+                      @click="handlePreview(file)"
+                    >
+                      棰勮
+                    </el-button>
+                  </div>
+                </el-card>
+              </template>
             </div>
           </div>
         </div>
@@ -393,6 +459,7 @@
         </el-descriptions-item>
 
         <!-- 浼氳闄勪欢 -->
+        鎴戠悊瑙f偍鐨勯渶姹傦紝鎮ㄥ笇鏈涘皢浼氳闄勪欢涓殑鍥剧墖鏂囦欢浠l-image鐨勯瑙堝浘褰㈠紡灞曠ず锛屽叾浠栨枃浠剁被鍨嬩繚鎸佸師鏈夌殑灞曠ず鏂瑰紡銆傝鎴戜慨鏀硅繖閮ㄥ垎浠g爜锛�
         <el-descriptions-item label="浼氳闄勪欢" :span="2">
           <div class="detail-attachments">
             <div
@@ -402,37 +469,94 @@
               "
               class="attachment-grid"
             >
+              <!-- 鍥剧墖闄勪欢 - 浣跨敤 el-image 棰勮褰㈠紡 -->
               <div
                 v-for="file in parseAttachments(currentRecord.attachment)"
                 :key="file.id || file.name"
                 class="attachment-card"
               >
-                <el-card shadow="hover" class="file-card">
-                  <div class="file-content">
-                    <i
-                      :class="getFileIcon(file.type || file.name)"
-                      class="file-icon"
-                    ></i>
-                    <div class="file-info">
-                      <div class="file-name" :title="file.name">
-                        {{ file.name }}
-                      </div>
-                      <div class="file-meta">
-                        <span class="file-size" v-if="file.size">{{
-                          formatFileSize(file.size)
-                        }}</span>
-                      </div>
+                <template v-if="isImageFile(file)">
+                  <!-- 鍥剧墖浣跨敤 el-image 棰勮 -->
+                  <el-image
+                    class="image-attachment"
+                    :src="getFileUrl(file)"
+                    :preview-src-list="getImagePreviewList(file)"
+                    fit="cover"
+                    :style="{ width: imageSize, height: imageSize }"
+                    lazy
+                  >
+                    <div slot="error" class="image-error">
+                      <i class="el-icon-picture-outline"></i>
+                      <span>鍔犺浇澶辫触</span>
+                    </div>
+                    <div slot="placeholder" class="image-loading">
+                      <i class="el-icon-loading"></i>
+                    </div>
+                  </el-image>
+                  <div class="image-info">
+                    <div class="file-name" :title="file.name">
+                      {{ file.name }}
+                    </div>
+                    <div class="file-actions">
+                      <el-button
+                        type="text"
+                        size="mini"
+                        @click="handleDownload(file)"
+                        icon="el-icon-download"
+                        title="涓嬭浇"
+                      />
+                      <el-button
+                        type="text"
+                        size="mini"
+                        @click="handlePreview(file)"
+                        icon="el-icon-view"
+                        title="棰勮"
+                      />
                     </div>
                   </div>
-                  <div class="file-actions" v-if="file.url">
-                    <el-button
-                      type="text"
-                      size="mini"
-                      @click="handleDownload(file)"
-                      >涓嬭浇</el-button
-                    >
-                  </div>
-                </el-card>
+                </template>
+
+                <template v-else>
+                  <!-- 闈炲浘鐗囨枃浠朵繚鎸佸師鏈夋牱寮� -->
+                  <el-card shadow="hover" class="file-card">
+                    <div class="file-content">
+                      <i
+                        :class="getFileIcon(file.type || file.name)"
+                        class="file-icon"
+                      ></i>
+                      <div class="file-info">
+                        <div class="file-name" :title="file.name">
+                          {{ file.name }}
+                        </div>
+                        <div class="file-meta">
+                          <span class="file-type">{{
+                            getFileTypeText(file)
+                          }}</span>
+                          <span class="file-size" v-if="file.size">
+                            {{ formatFileSize(file.size) }}
+                          </span>
+                        </div>
+                      </div>
+                    </div>
+                    <div class="file-actions" v-if="file.url">
+                      <el-button
+                        type="text"
+                        size="mini"
+                        @click="handleDownload(file)"
+                      >
+                        涓嬭浇
+                      </el-button>
+                      <el-button
+                        v-if="canPreview(file)"
+                        type="text"
+                        size="mini"
+                        @click="handlePreview(file)"
+                      >
+                        棰勮
+                      </el-button>
+                    </div>
+                  </el-card>
+                </template>
               </div>
             </div>
             <div v-else class="no-attachment">
@@ -474,7 +598,7 @@
     <el-dialog
       :title="`${isEditing ? '缂栬緫' : '鏂板'}浼氳`"
       :visible.sync="editDialogVisible"
-      width="700px"
+      width="800px"
       :before-close="handleEditClose"
     >
       <el-form
@@ -502,16 +626,16 @@
           </el-select>
         </el-form-item>
 
-        <el-form-item label="浼氳鍦扮偣" prop="locationId">
+        <el-form-item label="浼氳鍦扮偣" prop="locationName">
           <el-select
-            v-model="editForm.locationId"
+            v-model="editForm.locationName"
             placeholder="璇烽�夋嫨浼氳鍦扮偣"
             style="width: 100%"
           >
-            <el-option label="绗竴浼氳瀹�" :value="1" />
-            <el-option label="绗簩浼氳瀹�" :value="2" />
-            <el-option label="绗笁浼氳瀹�" :value="3" />
-            <el-option label="绾夸笂浼氳" :value="4" />
+            <el-option label="绗竴浼氳瀹�" value="绗竴浼氳瀹�" />
+            <el-option label="绗簩浼氳瀹�" value="绗簩浼氳瀹�" />
+            <el-option label="绗笁浼氳瀹�" value="绗笁浼氳瀹�" />
+            <el-option label="绾夸笂浼氳" value="绾夸笂浼氳" />
           </el-select>
         </el-form-item>
 
@@ -573,47 +697,84 @@
           />
         </el-form-item>
 
+        <!-- 淇敼浼氳闄勪欢閮ㄥ垎 -->
         <el-form-item label="浼氳闄勪欢">
-          <div class="attachment-upload-section">
-            <div class="upload-tip">涓婁紶浼氳鐩稿叧璧勬枡鏂囦欢</div>
-            <el-upload
-              class="attachment-upload"
-              action="#"
-              :auto-upload="false"
-              :on-change="handleAttachmentChange"
-              :file-list="editForm.attachmentFiles"
-              :limit="10"
-              multiple
-            >
-              <el-button size="small" type="primary" icon="el-icon-upload">
-                涓婁紶浼氳闄勪欢
-              </el-button>
-              <div slot="tip" class="el-upload__tip">
-                鏀寔鏂囨。銆佸浘鐗囩瓑鏍煎紡锛屽崟涓枃浠朵笉瓒呰繃20MB
-              </div>
-            </el-upload>
-            <div
-              v-if="
-                editForm.attachmentFiles && editForm.attachmentFiles.length > 0
-              "
-              class="uploaded-files"
-            >
-              <div
-                v-for="(file, index) in editForm.attachmentFiles"
-                :key="file.uid || index"
-                class="file-item"
+          <div class="attachment-section">
+            <div class="attachment-header">
+              <i class="el-icon-paperclip"></i>
+              <span class="attachment-title">浼氳闄勪欢涓婁紶</span>
+              <span class="attachment-tip"
+                >鏀寔涓婁紶鏂囨。銆佸浘鐗囩瓑鏂囦欢 (鏈�澶歿{ attachmentLimit }}涓�)</span
               >
-                <span class="file-name">{{ file.name }}</span>
-                <el-button
-                  type="text"
-                  size="mini"
-                  @click="handleRemoveAttachmentFile(index)"
-                  style="color: #F56C6C;"
-                >
-                  鍒犻櫎
-                </el-button>
-              </div>
             </div>
+
+            <!-- 浣跨敤 UploadAttachment 缁勪欢 -->
+            <UploadAttachment
+              ref="uploadAttachment"
+              :file-list="attachmentFileList"
+              :limit="attachmentLimit"
+              :accept="attachmentAccept"
+              @change="handleAttachmentChange"
+              @upload-success="handleAttachmentUploadSuccess"
+              @upload-error="handleAttachmentUploadError"
+              @remove="handleAttachmentRemove"
+            />
+          </div>
+
+          <!-- 浼氳闄勪欢鍒楄〃 -->
+          <div
+            class="attachment-list"
+            v-if="editForm.attachment && editForm.attachment.length > 0"
+          >
+            <div class="list-title">
+              宸蹭笂浼犻檮浠� ({{ editForm.attachment.length }})
+            </div>
+            <el-table
+              :data="editForm.attachment"
+              style="width: 100%"
+              size="small"
+              border
+            >
+              <el-table-column label="鏂囦欢鍚�" min-width="200">
+                <template #default="scope">
+                  <i
+                    class="el-icon-document"
+                    style="margin-right: 8px; color: #409EFF;"
+                  ></i>
+                  <span class="file-name">{{ scope.row.name }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="鏂囦欢绫诲瀷" width="100">
+                <template #default="scope">
+                  <el-tag size="small">{{
+                    getFileType(scope.row.name)
+                  }}</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="鏂囦欢澶у皬" width="100">
+                <template #default="scope">
+                  <span>{{ formatFileSize(scope.row.size) }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="鎿嶄綔" width="200">
+                <template #default="scope">
+                  <el-button
+                    size="mini"
+                    type="primary"
+                    @click="handlePreviewAttachment(scope.row)"
+                  >
+                    棰勮
+                  </el-button>
+                  <el-button
+                    size="mini"
+                    type="danger"
+                    @click="handleRemoveMeetingAttachment(scope.$index)"
+                  >
+                    鍒犻櫎
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
           </div>
         </el-form-item>
 
@@ -633,25 +794,86 @@
           </div>
         </el-form-item>
 
+        <!-- 淇敼浼氳绾闄勪欢閮ㄥ垎 -->
         <el-form-item label="绾闄勪欢">
-          <div class="attachment-upload-section">
-            <div class="upload-tip">涓婁紶涓庝細璁邯瑕佺浉鍏崇殑琛ュ厖鏉愭枡</div>
-            <el-upload
-              class="minutes-upload"
-              action="#"
-              :auto-upload="false"
-              :on-change="handleMinutesAttachmentChange"
-              :file-list="editForm.recordattachmentFiles"
-              :limit="5"
-              multiple
+          <div class="attachment-section">
+            <div class="attachment-header">
+              <i class="el-icon-paperclip"></i>
+              <span class="attachment-title">绾闄勪欢涓婁紶</span>
+              <span class="attachment-tip"
+                >鏀寔涓婁紶涓庣邯瑕佺浉鍏崇殑琛ュ厖鏉愭枡 (鏈�澶歿{
+                  minutesAttachmentLimit
+                }}涓�)</span
+              >
+            </div>
+
+            <UploadAttachment
+              ref="uploadMinutesAttachment"
+              :file-list="minutesAttachmentFileList"
+              :limit="minutesAttachmentLimit"
+              :accept="minutesAttachmentAccept"
+              @change="handleMinutesAttachmentChange"
+              @upload-success="handleMinutesUploadSuccess"
+              @upload-error="handleMinutesUploadError"
+              @remove="handleMinutesAttachmentRemove"
+            />
+          </div>
+
+          <div
+            class="attachment-list"
+            v-if="
+              editForm.recordattachment && editForm.recordattachment.length > 0
+            "
+          >
+            <div class="list-title">
+              宸蹭笂浼犵邯瑕侀檮浠� ({{ editForm.recordattachment.length }})
+            </div>
+            <el-table
+              :data="editForm.recordattachment"
+              style="width: 100%"
+              size="small"
+              border
             >
-              <el-button size="small" type="primary" icon="el-icon-upload">
-                涓婁紶绾闄勪欢
-              </el-button>
-              <div slot="tip" class="el-upload__tip">
-                鏀寔鍥剧墖銆佹枃妗g瓑鏍煎紡锛屽崟涓枃浠朵笉瓒呰繃10MB
-              </div>
-            </el-upload>
+              <el-table-column label="鏂囦欢鍚�" min-width="200">
+                <template #default="scope">
+                  <i
+                    class="el-icon-document"
+                    style="margin-right: 8px; color: #409EFF;"
+                  ></i>
+                  <span class="file-name">{{ scope.row.name }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="鏂囦欢绫诲瀷" width="100">
+                <template #default="scope">
+                  <el-tag size="small">{{
+                    getFileType(scope.row.name)
+                  }}</el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="鏂囦欢澶у皬" width="100">
+                <template #default="scope">
+                  <span>{{ formatFileSize(scope.row.size) }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="鎿嶄綔" width="200">
+                <template #default="scope">
+                  <el-button
+                    size="mini"
+                    type="primary"
+                    @click="handlePreviewMinutesAttachment(scope.row)"
+                  >
+                    棰勮
+                  </el-button>
+                  <el-button
+                    size="mini"
+                    type="danger"
+                    @click="handleRemoveMinutesAttachment(scope.$index)"
+                  >
+                    鍒犻櫎
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
           </div>
         </el-form-item>
 
@@ -672,6 +894,13 @@
         </el-button>
       </span>
     </el-dialog>
+    <!-- 鏂囦欢棰勮寮圭獥 -->
+    <FilePreviewDialog
+      :visible="previewVisible"
+      :file="currentPreviewFile"
+      @close="previewVisible = false"
+      @download="handleDownload"
+    />
   </div>
 </template>
 
@@ -684,9 +913,15 @@
   meetingDel,
   exporremeeting
 } from "@/api/officeManagementApi";
-
+import UploadAttachment from "@/components/UploadAttachment";
+import FilePreviewDialog from "@/components/FilePreviewDialog";
+import dayjs from "dayjs";
 export default {
   name: "MeetingManagement",
+  components: {
+    UploadAttachment,
+    FilePreviewDialog
+  },
   data() {
     return {
       // 鏌ヨ鍙傛暟
@@ -716,6 +951,7 @@
       isEditing: false,
       // 琛ㄦ牸鏁版嵁
       tableData: [],
+      imageSize: "100px", // 鍥剧墖鏄剧ず澶у皬
       // 缂栬緫琛ㄥ崟鏁版嵁
       editForm: this.getDefaultFormData(),
       // 琛ㄥ崟楠岃瘉瑙勫垯
@@ -742,7 +978,24 @@
         reminderMinutes: [
           { required: true, message: "璇疯緭鍏ユ彁鍓嶆彁閱掓椂闂�", trigger: "blur" }
         ]
-      }
+      },
+      // 闄勪欢鐩稿叧閰嶇疆
+      attachmentLimit: 10,
+      minutesAttachmentLimit: 5,
+      attachmentAccept:
+        ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar",
+      minutesAttachmentAccept: ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx",
+
+      // 鏂囦欢棰勮鐩稿叧
+      previewVisible: false,
+      currentPreviewFile: null,
+
+      // 闄勪欢鏂囦欢鍒楄〃
+      attachmentFileList: [],
+      minutesAttachmentFileList: [],
+
+      // 缂栬緫琛ㄥ崟鏁版嵁 - 淇敼榛樿鍊�
+      editForm: this.getDefaultFormData()
     };
   },
   mounted() {
@@ -783,7 +1036,111 @@
         this.loading = false;
       }
     },
+    // 淇敼鑾峰彇鏂囦欢绫诲瀷鏂规硶
+    getFileType(fileName) {
+      if (!fileName) return "other";
+      const extension = fileName
+        .split(".")
+        .pop()
+        .toLowerCase();
+      const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
+      const pdfTypes = ["pdf"];
+      const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
+      const zipTypes = ["zip", "rar"];
 
+      if (imageTypes.includes(extension)) return "image";
+      if (pdfTypes.includes(extension)) return "pdf";
+      if (officeTypes.includes(extension)) return "office";
+      if (zipTypes.includes(extension)) return "archive";
+      return "other";
+    },
+    // 鍒ゆ柇鏄惁涓哄浘鐗囨枃浠�
+    isImageFile(file) {
+      if (!file || !file.name) return false;
+      const imageExtensions = [
+        "jpg",
+        "jpeg",
+        "png",
+        "gif",
+        "bmp",
+        "webp",
+        "svg"
+      ];
+      const extension = file.name
+        .split(".")
+        .pop()
+        .toLowerCase();
+      return imageExtensions.includes(extension);
+    },
+
+    // 鑾峰彇鏂囦欢URL
+    getFileUrl(file) {
+      return file.url || file.path || file.fileUrl || "";
+    },
+
+    // 鑾峰彇鍥剧墖棰勮鍒楄〃
+    getImagePreviewList(file) {
+      const url = this.getFileUrl(file);
+      if (!url) return [];
+      return [url];
+    },
+    // 鑾峰彇鏂囦欢绫诲瀷鏂囨湰
+    getFileTypeText(file) {
+      if (!file.name) return "鏂囦欢";
+      const ext = file.name
+        .split(".")
+        .pop()
+        .toLowerCase();
+      const typeMap = {
+        pdf: "PDF鏂囨。",
+        doc: "Word鏂囨。",
+        docx: "Word鏂囨。",
+        xls: "Excel琛ㄦ牸",
+        xlsx: "Excel琛ㄦ牸",
+        ppt: "PPT婕旂ず",
+        pptx: "PPT婕旂ず",
+        zip: "鍘嬬缉鍖�",
+        rar: "鍘嬬缉鍖�",
+        txt: "鏂囨湰鏂囨。",
+        jpg: "鍥剧墖",
+        jpeg: "鍥剧墖",
+        png: "鍥剧墖",
+        gif: "鍥剧墖"
+      };
+      return typeMap[ext] || "鏂囦欢";
+    },
+
+    // 鍒ゆ柇鏂囦欢鏄惁鍙互棰勮
+    canPreview(file) {
+      if (!file.name) return false;
+      const previewableExtensions = ["pdf", "jpg", "jpeg", "png", "gif", "txt"];
+      const extension = file.name
+        .split(".")
+        .pop()
+        .toLowerCase();
+      return previewableExtensions.includes(extension);
+    },
+
+    // 鏂囦欢棰勮
+    handlePreview(file) {
+      this.currentPreviewFile = {
+        fileName: file.name,
+        fileUrl: this.getFileUrl(file),
+        fileType: this.getFileType(file.name)
+      };
+      this.previewVisible = true;
+    },
+    // 闄勪欢杞崲涓轰笂浼犳枃浠跺垪琛�
+    parseAttachmentToFileList(attachments) {
+      if (!attachments || !Array.isArray(attachments)) return [];
+      return attachments.map((item, index) => ({
+        uid: item.id || `attachment-${index}-${Date.now()}`,
+        name: item.name || item.fileName,
+        url: item.url || item.path || item.fileUrl,
+        size: item.size,
+        status: "success"
+      }));
+    },
     // 鑾峰彇鏂囦欢鍥炬爣
     getFileIcon(fileName) {
       if (!fileName) return "el-icon-document";
@@ -917,9 +1274,9 @@
       }
     },
 
-    // 鏍煎紡鍖栨枃浠跺ぇ灏�
+    // 鏂囦欢澶у皬鏍煎紡鍖�
     formatFileSize(bytes) {
-      if (!bytes) return "0 B";
+      if (!bytes || bytes === 0) return "0 B";
       const k = 1024;
       const sizes = ["B", "KB", "MB", "GB"];
       const i = Math.floor(Math.log(bytes) / Math.log(k));
@@ -950,7 +1307,20 @@
       try {
         const response = await meetingInfo(id);
         if (response.code === 200) {
-          this.currentRecord = response.data || {};
+          const data = response.data || {};
+          // 瑙f瀽闄勪欢
+          if (data.attachment && typeof data.attachment === "string") {
+            data.attachment = this.parseAttachments(data.attachment);
+          }
+          if (
+            data.recordattachment &&
+            typeof data.recordattachment === "string"
+          ) {
+            data.recordattachment = this.parseAttachments(
+              data.recordattachment
+            );
+          }
+          this.currentRecord = data;
           this.detailDialogVisible = true;
         } else {
           this.$message.error(response.msg || "鑾峰彇璇︽儏澶辫触");
@@ -965,6 +1335,8 @@
     handleAdd() {
       this.isEditing = false;
       this.editForm = this.getDefaultFormData();
+      this.attachmentFileList = [];
+      this.minutesAttachmentFileList = [];
       this.editDialogVisible = true;
       this.$nextTick(() => {
         this.$refs.editForm && this.$refs.editForm.clearValidate();
@@ -977,21 +1349,26 @@
         const response = await meetingInfo(id);
         if (response.code === 200) {
           this.isEditing = true;
-          this.currentRecord = response.data || {};
-          this.editForm = { ...response.data };
+          const data = response.data || {};
 
           // 瑙f瀽闄勪欢
-          if (this.editForm.attachment) {
-            this.editForm.attachmentFiles = this.parseAttachments(
-              this.editForm.attachment
+          if (data.attachment) {
+            data.attachment = this.parseAttachments(data.attachment);
+            this.attachmentFileList = this.parseAttachmentToFileList(
+              data.attachment
             );
           }
-          if (this.editForm.recordattachment) {
-            this.editForm.recordattachmentFiles = this.parseAttachments(
-              this.editForm.recordattachment
+          if (data.recordattachment) {
+            data.recordattachment = this.parseAttachments(
+              data.recordattachment
+            );
+            this.minutesAttachmentFileList = this.parseAttachmentToFileList(
+              data.recordattachment
             );
           }
 
+          this.currentRecord = data;
+          this.editForm = { ...data };
           this.editDialogVisible = true;
           this.detailDialogVisible = false;
           this.$nextTick(() => {
@@ -1070,33 +1447,156 @@
       }
     },
 
-    // 鏂囦欢涓婁紶澶勭悊
-    handleAttachmentChange(file, fileList) {
-      this.editForm.attachmentFiles = fileList;
+    // 闄勪欢鍙樺寲澶勭悊
+    handleAttachmentChange(fileList) {
+      this.attachmentFileList = fileList;
     },
 
-    handleMinutesAttachmentChange(file, fileList) {
-      this.editForm.recordattachmentFiles = fileList;
+    handleMinutesAttachmentChange(fileList) {
+      this.minutesAttachmentFileList = fileList;
+    },
+    // 闄勪欢涓婁紶鎴愬姛澶勭悊
+    handleAttachmentUploadSuccess({ file, fileList, response }) {
+      if (response && response.code === 200) {
+        if (!this.editForm.attachment) {
+          this.editForm.attachment = [];
+        }
+
+        console.log(file, "file");
+        console.log(response, "response");
+
+        const attachmentObj = {
+          name: file.name,
+          url: response.data || file.url,
+          fileName: file.name,
+          size: file.size || 0,
+          type: this.getFileExtension(file.name),
+          createTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
+        };
+        console.log(this.editForm.attachment, "this.editForm.attachment");
+
+        this.editForm.attachment.push(attachmentObj);
+        console.log(this.editForm.attachment, "this.editForm.attachment");
+
+        this.$message.success("浼氳闄勪欢涓婁紶鎴愬姛");
+      }
+    },
+    handleMinutesUploadSuccess({ file, fileList, response }) {
+      if (response && response.code === 200) {
+        if (!this.editForm.recordattachment) {
+          this.editForm.recordattachment = [];
+        }
+
+        const attachmentObj = {
+          name: file.name,
+          url: response.data || file.url,
+          fileName: file.name,
+          size: file.size || 0,
+          type: this.getFileExtension(file.name),
+          createTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
+        };
+        this.editForm.recordattachment.push(attachmentObj);
+        this.$message.success("绾闄勪欢涓婁紶鎴愬姛");
+      }
+    },
+    // 闄勪欢涓婁紶閿欒澶勭悊
+    handleAttachmentUploadError({ file, fileList, error }) {
+      console.error("浼氳闄勪欢涓婁紶澶辫触:", error);
+      this.$message.error("鏂囦欢涓婁紶澶辫触锛岃閲嶈瘯");
     },
 
-    // 鍒犻櫎宸蹭笂浼犵殑鏂囦欢
-    handleRemoveAttachmentFile(index) {
-      this.editForm.attachmentFiles.splice(index, 1);
+    handleMinutesUploadError({ file, fileList, error }) {
+      console.error("绾闄勪欢涓婁紶澶辫触:", error);
+      this.$message.error("鏂囦欢涓婁紶澶辫触锛岃閲嶈瘯");
+    },
+    // 闄勪欢绉婚櫎澶勭悊
+    handleAttachmentRemove(file) {
+      if (file.url && this.editForm.attachment) {
+        const index = this.editForm.attachment.findIndex(
+          item =>
+            item.url === file.url ||
+            item.path === file.url ||
+            item.fileUrl === file.url
+        );
+        if (index > -1) {
+          this.editForm.attachment.splice(index, 1);
+        }
+      }
     },
 
+    handleMinutesAttachmentRemove(file) {
+      if (file.url && this.editForm.recordattachment) {
+        const index = this.editForm.recordattachment.findIndex(
+          item =>
+            item.url === file.url ||
+            item.path === file.url ||
+            item.fileUrl === file.url
+        );
+        if (index > -1) {
+          this.editForm.recordattachment.splice(index, 1);
+        }
+      }
+    },
+    // 鎵嬪姩鍒犻櫎闄勪欢
+    handleRemoveMeetingAttachment(index) {
+      if (this.editForm.attachment && this.editForm.attachment[index]) {
+        this.editForm.attachment.splice(index, 1);
+        this.attachmentFileList.splice(index, 1);
+        this.$message.success("浼氳闄勪欢鍒犻櫎鎴愬姛");
+      }
+    },
+
+    handleRemoveMinutesAttachment(index) {
+      if (
+        this.editForm.recordattachment &&
+        this.editForm.recordattachment[index]
+      ) {
+        this.editForm.recordattachment.splice(index, 1);
+        this.minutesAttachmentFileList.splice(index, 1);
+        this.$message.success("绾闄勪欢鍒犻櫎鎴愬姛");
+      }
+    },
+    // 鏂囦欢棰勮
+    handlePreviewAttachment(file) {
+      this.currentPreviewFile = {
+        fileName: file.name || file.fileName,
+        fileUrl: file.url || file.path || file.fileUrl,
+        fileType: this.getFileType(file.name)
+      };
+      this.previewVisible = true;
+    },
+
+    handlePreviewMinutesAttachment(file) {
+      this.currentPreviewFile = {
+        fileName: file.name || file.fileName,
+        fileUrl: file.url || file.path || file.fileUrl,
+        fileType: this.getFileType(file.name)
+      };
+      this.previewVisible = true;
+    },
     // 鏂囦欢涓嬭浇
     handleDownload(file) {
       if (file.url) {
         const link = document.createElement("a");
         link.href = file.url;
-        link.download = file.name;
+        link.download = file.name || file.fileName || "download";
+        link.style.display = "none";
+        document.body.appendChild(link);
         link.click();
-        this.$message.success(`寮�濮嬩笅杞�: ${file.name}`);
+        document.body.removeChild(link);
+        this.$message.success("寮�濮嬩笅杞芥枃浠�");
       } else {
-        this.$message.warning("鏂囦欢鍦板潃涓嶅瓨鍦�");
+        this.$message.warning("鏂囦欢鍦板潃涓嶅瓨鍦紝鏃犳硶涓嬭浇");
       }
     },
-
+    // 鑾峰彇鏂囦欢鎵╁睍鍚�
+    getFileExtension(filename) {
+      if (!filename) return "";
+      return filename
+        .split(".")
+        .pop()
+        .toLowerCase();
+    },
     // 淇濆瓨璁板綍
     async handleSave() {
       try {
@@ -1113,34 +1613,55 @@
           }
         }
 
+        // 妫�鏌ユ槸鍚︽湁鏈笂浼犲畬鎴愮殑鏂囦欢
+        const pendingFiles = [
+          ...this.attachmentFileList.filter(item => item.status !== "success"),
+          ...this.minutesAttachmentFileList.filter(
+            item => item.status !== "success"
+          )
+        ];
+
+        if (pendingFiles.length > 0) {
+          this.$message.warning(
+            "杩樻湁鏂囦欢鏈笂浼犲畬鎴愶紝璇峰厛涓婁紶鎵�鏈夋枃浠舵垨绉婚櫎鏈笂浼犵殑鏂囦欢"
+          );
+          return;
+        }
+
         this.saveLoading = true;
 
-        // 澶勭悊闄勪欢
+        // 鍑嗗鏁版嵁
         const formData = { ...this.editForm };
 
-        if (formData.attachmentFiles) {
+        // 澶勭悊闄勪欢涓篔SON瀛楃涓�
+        if (formData.attachment && Array.isArray(formData.attachment)) {
           formData.attachment = JSON.stringify(
-            formData.attachmentFiles.map(file => ({
-              name: file.name,
-              url: file.url || "",
-              size: file.size || 0,
-              type: file.type || file.name.split(".").pop()
+            formData.attachment.map(item => ({
+              name: item.name || item.fileName,
+              url: item.url || item.path || item.fileUrl,
+              size: item.size || 0,
+              type:
+                item.type || this.getFileExtension(item.name || item.fileName)
             }))
           );
         }
 
-        if (formData.recordattachmentFiles) {
+        if (
+          formData.recordattachment &&
+          Array.isArray(formData.recordattachment)
+        ) {
           formData.recordattachment = JSON.stringify(
-            formData.recordattachmentFiles.map(file => ({
-              name: file.name,
-              url: file.url || "",
-              size: file.size || 0,
-              type: file.type || file.name.split(".").pop()
+            formData.recordattachment.map(item => ({
+              name: item.name || item.fileName,
+              url: item.url || item.path || item.fileUrl,
+              size: item.size || 0,
+              type:
+                item.type || this.getFileExtension(item.name || item.fileName)
             }))
           );
         }
 
-        // 娓呯悊鏂囦欢鍒楄〃瀛楁
+        // 娓呯悊涓存椂瀛楁
         delete formData.attachmentFiles;
         delete formData.recordattachmentFiles;
 
@@ -1179,6 +1700,8 @@
       this.editDialogVisible = false;
       this.currentRecord = {};
       this.editForm = this.getDefaultFormData();
+      this.attachmentFileList = [];
+      this.minutesAttachmentFileList = [];
       this.$nextTick(() => {
         this.$refs.editForm && this.$refs.editForm.clearValidate();
       });
@@ -1216,7 +1739,7 @@
       console.log("鎺掑簭鍙樺寲:", sort);
     },
 
-    // 鑾峰彇榛樿琛ㄥ崟鏁版嵁
+    // 榛樿琛ㄥ崟鏁版嵁
     getDefaultFormData() {
       return {
         id: null,
@@ -1227,19 +1750,14 @@
         endTime: "",
         summary: "",
         content: "",
-        attachment: null,
-        attachmentFiles: [],
-        status: 1, // 榛樿寰呭紑濮�
-        isRecurring: 0,
-        recurringPattern: null,
-        parentMeetingId: null,
-        reminderMinutes: 30,
+        attachment: [], // 鏀逛负鏁扮粍
         recordcontent: "",
-        recordattachment: null,
-        recordattachmentFiles: [],
+        recordattachment: [], // 鏀逛负鏁扮粍
         recorderBy: "",
         remark: "",
-        approvalStatus: 0 // 榛樿寰呭鏍�
+        status: 1,
+        reminderMinutes: 30,
+        approvalStatus: 0
       };
     }
   }
@@ -1247,6 +1765,170 @@
 </script>
 
 <style scoped>
+.meeting-management {
+  padding: 20px;
+}
+
+.attachment-section {
+  margin-bottom: 16px;
+}
+
+.attachment-header {
+  display: flex;
+  align-items: center;
+  margin-bottom: 16px;
+  padding: 8px 0;
+  border-bottom: 1px solid #ebeef5;
+}
+
+.attachment-title {
+  font-weight: bold;
+  margin: 0 8px;
+}
+
+.attachment-tip {
+  font-size: 12px;
+  color: #909399;
+}
+
+.attachment-list {
+  margin-top: 16px;
+}
+
+.list-title {
+  font-weight: bold;
+  margin-bottom: 12px;
+  color: #303133;
+}
+/* 鍥剧墖闄勪欢鏍峰紡 */
+.image-attachment {
+  border-radius: 4px;
+  border: 1px solid #ebeef5;
+  cursor: pointer;
+  transition: all 0.3s;
+  margin-bottom: 8px;
+}
+
+.image-attachment:hover {
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+  transform: translateY(-2px);
+}
+
+.image-info {
+  text-align: center;
+  padding: 4px 0;
+}
+
+.image-info .file-name {
+  font-size: 12px;
+  color: #606266;
+  margin-bottom: 4px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  max-width: 100px;
+}
+
+.image-info .file-actions {
+  display: flex;
+  justify-content: center;
+  gap: 8px;
+}
+
+.image-loading,
+.image-error {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+  color: #909399;
+  font-size: 12px;
+}
+
+.image-loading i,
+.image-error i {
+  font-size: 20px;
+  margin-bottom: 4px;
+}
+
+/* 鏂囦欢鍗$墖鏍峰紡 */
+.file-card {
+  width: 100%;
+  min-height: 60px;
+  margin-bottom: 8px;
+}
+
+.file-content {
+  display: flex;
+  align-items: center;
+}
+
+.file-icon {
+  font-size: 24px;
+  margin-right: 12px;
+  color: #409eff;
+  flex-shrink: 0;
+}
+
+.file-info {
+  flex: 1;
+  min-width: 0;
+}
+
+.file-name {
+  font-size: 13px;
+  font-weight: 500;
+  margin-bottom: 4px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.file-meta {
+  display: flex;
+  justify-content: space-between;
+  font-size: 12px;
+  color: #909399;
+}
+
+.file-actions {
+  margin-top: 8px;
+  text-align: right;
+}
+
+/* 闄勪欢缃戞牸甯冨眬 */
+.attachment-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
+  gap: 16px;
+}
+
+.attachment-card {
+  display: flex;
+  flex-direction: column;
+}
+
+/* 鍝嶅簲寮忚皟鏁� */
+@media (max-width: 768px) {
+  .attachment-grid {
+    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
+    gap: 12px;
+  }
+
+  .image-attachment {
+    width: 80px !important;
+    height: 80px !important;
+  }
+}
+.file-name {
+  font-size: 13px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+/* 鍏朵粬鏍峰紡淇濇寔涓嶅彉 */
 .meeting-management {
   padding: 20px;
 }
@@ -1276,6 +1958,7 @@
 .attachment-item {
   margin-bottom: 8px;
 }
+
 .minutes-content {
   margin-bottom: 16px;
 }
@@ -1291,6 +1974,7 @@
     margin: 0 -20px;
   }
 }
+
 /* 鍝嶅簲寮忚璁� */
 @media (max-width: 768px) {
   .page-header {
@@ -1304,6 +1988,7 @@
     justify-content: space-between;
   }
 }
+
 /* 鏂板闄勪欢鐩稿叧鏍峰紡 */
 .attachment-upload-section {
   border: 1px solid #ebeef5;

--
Gitblit v1.9.3