From 87e331767b3ce416c957b7336e94b9ba208f0efb Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期四, 16 四月 2026 18:08:31 +0800
Subject: [PATCH] 维护

---
 src/views/OfficeRelated/conference/index.vue | 1310 +++++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 1,000 insertions(+), 310 deletions(-)

diff --git a/src/views/OfficeRelated/conference/index.vue b/src/views/OfficeRelated/conference/index.vue
index 5b87c95..bc55057 100644
--- a/src/views/OfficeRelated/conference/index.vue
+++ b/src/views/OfficeRelated/conference/index.vue
@@ -2,7 +2,6 @@
   <div class="meeting-management">
     <!-- 椤甸潰澶撮儴 -->
     <div class="page-header">
-      <h2>浼氳绠$悊</h2>
       <div class="header-actions">
         <el-button type="primary" icon="el-icon-plus" @click="handleAdd">
           鏂板缓浼氳
@@ -17,7 +16,11 @@
     <el-card class="filter-card">
       <el-form :model="queryParams" inline>
         <el-form-item label="浼氳绫诲瀷">
-          <el-select v-model="queryParams.meetingType" clearable placeholder="璇烽�夋嫨">
+          <el-select
+            v-model="queryParams.meetingType"
+            clearable
+            placeholder="璇烽�夋嫨"
+          >
             <el-option label="绉戠爺浼氳" value="research" />
             <el-option label="鏃ュ父浼氳" value="daily" />
             <el-option label="椤圭洰浼氳" value="project" />
@@ -33,7 +36,7 @@
             style="width: 150px"
           />
         </el-form-item>
-        <el-form-item label="鏃堕棿鑼冨洿">
+        <el-form-item label="浼氳寮�濮嬫椂闂磋寖鍥�">
           <el-date-picker
             v-model="queryParams.dateRange"
             type="daterange"
@@ -44,12 +47,27 @@
           />
         </el-form-item>
         <el-form-item label="鐘舵��">
-          <el-select v-model="queryParams.status" clearable placeholder="璇烽�夋嫨">
-            <el-option label="寰呭紑濮�" value="pending" />
-            <el-option label="杩涜涓�" value="ongoing" />
-            <el-option label="宸茬粨鏉�" value="completed" />
-            <el-option label="宸插彇娑�" value="cancelled" />
+          <el-select
+            v-model="queryParams.status"
+            clearable
+            placeholder="璇烽�夋嫨"
+          >
+            <el-option label="寰呭紑濮�" value="1" />
+            <el-option label="杩涜涓�" value="2" />
+            <el-option label="宸茬粨鏉�" value="3" />
+            <el-option label="宸插彇娑�" value="4" />
+            <el-option label="寰呭鏍�" value="0" />
+            <el-option label="宸查�氳繃" value="1" />
+            <el-option label="宸查┏鍥�" value="2" />
           </el-select>
+        </el-form-item>
+        <el-form-item label="浼氳涓婚">
+          <el-input
+            v-model="queryParams.title"
+            placeholder="璇疯緭鍏ヤ細璁富棰�"
+            clearable
+            style="width: 150px"
+          />
         </el-form-item>
         <el-form-item>
           <el-button type="primary" @click="handleQuery">鏌ヨ</el-button>
@@ -67,63 +85,137 @@
         style="width: 100%"
         @sort-change="handleSortChange"
       >
-        <el-table-column prop="id" label="ID" width="80" fixed />
-        <el-table-column prop="title" label="浼氳涓婚" width="200" fixed>
+        <el-table-column prop="id" label="ID" width="80" fixed align="center" />
+        <el-table-column
+          prop="title"
+          align="center"
+          label="浼氳涓婚"
+          width="200"
+          fixed
+        >
           <template #default="scope">
-            <el-button type="text" @click="handleView(scope.row)">
+            <el-button type="text" @click="handleView(scope.row.id)">
               {{ scope.row.title }}
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column prop="meetingType" label="浼氳绫诲瀷" width="120">
+        <el-table-column
+          align="center"
+          prop="meetingType"
+          label="浼氳绫诲瀷"
+          width="120"
+        >
           <template #default="scope">
-            <el-tag :type="getMeetingTypeTag(scope.row.meetingType)">
-              {{ getMeetingTypeText(scope.row.meetingType) }}
+            <el-tag :type="getMeetingTypeTag(scope.row.typeId)">
+              {{ getMeetingTypeText(scope.row.typeId) }}
             </el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="participants" label="鍙備細浜哄憳" width="180" show-overflow-tooltip>
+        <el-table-column
+          align="center"
+          label="浼氳鐘舵��"
+          width="100"
+          fixed="right"
+        >
           <template #default="scope">
-            <span>{{ scope.row.participants.join(', ') }}</span>
+            <el-tag :type="getMeetingStatusTag(scope.row.status)">
+              {{ getMeetingStatusText(scope.row.status) }}
+            </el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="location" label="浼氳鍦扮偣" width="150" />
-        <el-table-column prop="startTime" label="寮�濮嬫椂闂�" width="160" sortable>
+        <el-table-column
+          align="center"
+          prop="organizerName"
+          label="缁勭粐鑰�"
+          width="120"
+        />
+        <el-table-column
+          align="center"
+          prop="locationName"
+          label="浼氳鍦扮偣"
+          width="150"
+        />
+        <el-table-column
+          align="center"
+          prop="startTime"
+          label="寮�濮嬫椂闂�"
+          width="160"
+          sortable
+        >
           <template #default="scope">
             <span>{{ formatDateTime(scope.row.startTime) }}</span>
           </template>
         </el-table-column>
-        <el-table-column prop="endTime" label="缁撴潫鏃堕棿" width="160" sortable>
+        <el-table-column
+          align="center"
+          prop="endTime"
+          label="缁撴潫鏃堕棿"
+          width="160"
+          sortable
+        >
           <template #default="scope">
             <span>{{ formatDateTime(scope.row.endTime) }}</span>
           </template>
         </el-table-column>
-        <el-table-column prop="duration" label="鎸佺画鏃堕棿" width="100">
+        <el-table-column
+          align="center"
+          prop="duration"
+          label="鎸佺画鏃堕棿"
+          width="100"
+        >
           <template #default="scope">
             <span>{{ calculateDuration(scope.row) }}</span>
           </template>
         </el-table-column>
-        <el-table-column prop="summary" label="浼氳姒傝" min-width="200" show-overflow-tooltip />
-        <el-table-column prop="status" label="鐘舵��" width="100" fixed="right">
+        <el-table-column
+          align="center"
+          prop="summary"
+          label="浼氳姒傝"
+          min-width="200"
+          show-overflow-tooltip
+        />
+        <el-table-column align="center" label="浼氳绾" width="120">
           <template #default="scope">
-            <el-tag :type="getStatusTag(scope.row.status)">
-              {{ getStatusText(scope.row.status) }}
+            <el-button
+              size="mini"
+              type="text"
+              @click="handleViewMinutes(scope.row)"
+              :disabled="!scope.row.recordcontent"
+            >
+              {{ scope.row.recordcontent ? "鏌ョ湅绾" : "鏆傛棤" }}
+            </el-button>
+          </template>
+        </el-table-column>
+        <el-table-column align="center" label="瀹℃牳鐘舵��" width="100">
+          <template #default="scope">
+            <el-tag :type="getApprovalStatusTag(scope.row.approvalStatus)">
+              {{ getApprovalStatusText(scope.row.approvalStatus) }}
             </el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="鎿嶄綔" width="200" fixed="right">
+        <el-table-column label="鎿嶄綔" align="center" width="200" fixed="right">
           <template #default="scope">
-            <el-button size="mini" type="text" @click="handleView(scope.row)">
+            <el-button
+              size="mini"
+              type="text"
+              @click="handleView(scope.row.id)"
+            >
               鏌ョ湅
             </el-button>
-            <el-button size="mini" type="text" @click="handleEdit(scope.row)">
+            <el-button
+              size="mini"
+              type="text"
+              @click="handleEdit(scope.row.id)"
+              :disabled="scope.row.delFlag === 1"
+            >
               缂栬緫
             </el-button>
             <el-button
               size="mini"
               type="text"
-              @click="handleCopy(scope.row)"
+              @click="handleCopy(scope.row.id)"
               style="color: #67C23A;"
+              :disabled="scope.row.delFlag === 1"
             >
               澶嶅埗
             </el-button>
@@ -132,6 +224,7 @@
               type="text"
               @click="handleDelete(scope.row)"
               style="color: #F56C6C;"
+              :disabled="scope.row.delFlag === 1"
             >
               鍒犻櫎
             </el-button>
@@ -142,15 +235,100 @@
       <!-- 鍒嗛〉 -->
       <div class="pagination-container">
         <el-pagination
-          :current-page="pagination.currentPage"
+          :current-page="pagination.pageNum"
           :page-size="pagination.pageSize"
           :total="pagination.total"
           layout="total, sizes, prev, pager, next, jumper"
+          :page-sizes="[10, 20, 50, 100]"
           @size-change="handleSizeChange"
           @current-change="handleCurrentChange"
         />
       </div>
     </el-card>
+
+    <!-- 浼氳绾瀵硅瘽妗� -->
+    <el-dialog
+      title="浼氳绾"
+      :visible.sync="minutesDialogVisible"
+      width="700px"
+    >
+      <div v-if="currentRecord.recordcontent">
+        <el-alert
+          title="浼氳绾璇︽儏"
+          type="info"
+          :closable="false"
+          style="margin-bottom: 16px;"
+        />
+        <div class="minutes-content">
+          <el-card>
+            <div
+              style="white-space: pre-line; line-height: 1.6; max-height: 300px; overflow-y: auto;"
+            >
+              {{ currentRecord.recordcontent }}
+            </div>
+          </el-card>
+        </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
+              v-for="file in parseAttachments(currentRecord.recordattachment)"
+              :key="file.id || file.name"
+              class="attachment-item"
+            >
+              <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
+                >
+              </el-link>
+            </div>
+          </div>
+        </div>
+
+        <div
+          class="minutes-meta"
+          style="margin-top: 16px; color: #909399; font-size: 12px;"
+        >
+          <span
+            >璁板綍鏃堕棿: {{ formatDateTime(currentRecord.recorderTime) }}</span
+          >
+          <span style="margin-left: 16px;"
+            >璁板綍浜�: {{ currentRecord.recorderBy || "鏈寚瀹�" }}</span
+          >
+        </div>
+      </div>
+      <div v-else>
+        <el-empty description="鏆傛棤浼氳绾"></el-empty>
+      </div>
+      <span slot="footer">
+        <el-button @click="minutesDialogVisible = false">鍏抽棴</el-button>
+        <el-button
+          type="primary"
+          @click="handleEdit(currentRecord.id)"
+          v-if="currentRecord.recordcontent"
+        >
+          缂栬緫绾
+        </el-button>
+      </span>
+    </el-dialog>
 
     <!-- 鏌ョ湅璇︽儏瀵硅瘽妗� -->
     <el-dialog
@@ -159,53 +337,136 @@
       width="800px"
       :before-close="handleDetailClose"
     >
-      <el-descriptions :column="2" border v-if="currentRecord">
-        <el-descriptions-item label="浼氳涓婚">{{ currentRecord.title }}</el-descriptions-item>
+      <el-descriptions :column="2" border v-if="currentRecord.id">
+        <el-descriptions-item label="浼氳缂栧彿">{{
+          currentRecord.meetingNumber
+        }}</el-descriptions-item>
+        <el-descriptions-item label="浼氳涓婚">{{
+          currentRecord.title
+        }}</el-descriptions-item>
         <el-descriptions-item label="浼氳绫诲瀷">
-          <el-tag :type="getMeetingTypeTag(currentRecord.meetingType)">
-            {{ getMeetingTypeText(currentRecord.meetingType) }}
+          <el-tag :type="getMeetingTypeTag(currentRecord.typeId)">
+            {{ getMeetingTypeText(currentRecord.typeId) }}
           </el-tag>
         </el-descriptions-item>
-        <el-descriptions-item label="鍙備細浜哄憳" :span="2">
-          <el-tag
-            v-for="participant in currentRecord.participants"
-            :key="participant"
-            type="info"
-            size="small"
-            style="margin-right: 8px; margin-bottom: 8px;"
-          >
-            {{ participant }}
-          </el-tag>
-        </el-descriptions-item>
-        <el-descriptions-item label="浼氳鍦扮偣">{{ currentRecord.location }}</el-descriptions-item>
         <el-descriptions-item label="浼氳鐘舵��">
-          <el-tag :type="getStatusTag(currentRecord.status)">
-            {{ getStatusText(currentRecord.status) }}
+          <el-tag :type="getMeetingStatusTag(currentRecord.status)">
+            {{ getMeetingStatusText(currentRecord.status) }}
           </el-tag>
         </el-descriptions-item>
-        <el-descriptions-item label="寮�濮嬫椂闂�">{{ formatDateTime(currentRecord.startTime) }}</el-descriptions-item>
-        <el-descriptions-item label="缁撴潫鏃堕棿">{{ formatDateTime(currentRecord.endTime) }}</el-descriptions-item>
-        <el-descriptions-item label="鎸佺画鏃堕棿">{{ calculateDuration(currentRecord) }}</el-descriptions-item>
-        <el-descriptions-item label="鍒涘缓浜�">{{ currentRecord.creator }}</el-descriptions-item>
+        <el-descriptions-item label="缁勭粐鑰�">{{
+          currentRecord.organizerName || currentRecord.createBy
+        }}</el-descriptions-item>
+        <el-descriptions-item label="浼氳鍦扮偣">{{
+          currentRecord.locationName || currentRecord.locationId
+        }}</el-descriptions-item>
+        <el-descriptions-item label="寮�濮嬫椂闂�">{{
+          formatDateTime(currentRecord.startTime)
+        }}</el-descriptions-item>
+        <el-descriptions-item label="缁撴潫鏃堕棿">{{
+          formatDateTime(currentRecord.endTime)
+        }}</el-descriptions-item>
+        <el-descriptions-item label="鎸佺画鏃堕棿">{{
+          calculateDuration(currentRecord)
+        }}</el-descriptions-item>
+        <el-descriptions-item label="瀹℃牳鐘舵��">
+          <el-tag :type="getApprovalStatusTag(currentRecord.approvalStatus)">
+            {{ getApprovalStatusText(currentRecord.approvalStatus) }}
+          </el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="瀹℃牳浜�">{{
+          currentRecord.approverBy || "鏈鏍�"
+        }}</el-descriptions-item>
+        <el-descriptions-item label="瀹℃牳鏃堕棿">{{
+          currentRecord.approvalTime
+            ? formatDateTime(currentRecord.approvalTime)
+            : "鏈鏍�"
+        }}</el-descriptions-item>
         <el-descriptions-item label="浼氳姒傝" :span="2">
           {{ currentRecord.summary }}
         </el-descriptions-item>
         <el-descriptions-item label="浼氳鍐呭" :span="2">
-          <div style="white-space: pre-line; max-height: 300px; overflow-y: auto;">
-            {{ currentRecord.content }}
+          <div
+            v-html="currentRecord.content"
+            style="white-space: pre-line; max-height: 300px; overflow-y: auto;"
+          ></div>
+        </el-descriptions-item>
+
+        <!-- 浼氳闄勪欢 -->
+        <el-descriptions-item label="浼氳闄勪欢" :span="2">
+          <div class="detail-attachments">
+            <div
+              v-if="
+                currentRecord.attachment &&
+                  parseAttachments(currentRecord.attachment).length > 0
+              "
+              class="attachment-grid"
+            >
+              <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>
+                    </div>
+                  </div>
+                  <div class="file-actions" v-if="file.url">
+                    <el-button
+                      type="text"
+                      size="mini"
+                      @click="handleDownload(file)"
+                      >涓嬭浇</el-button
+                    >
+                  </div>
+                </el-card>
+              </div>
+            </div>
+            <div v-else class="no-attachment">
+              <el-empty description="鏆傛棤浼氳闄勪欢" :image-size="50"></el-empty>
+            </div>
           </div>
         </el-descriptions-item>
-        <el-descriptions-item label="闄勪欢" :span="2" v-if="currentRecord.attachments && currentRecord.attachments.length">
-          <div v-for="file in currentRecord.attachments" :key="file.id" class="attachment-item">
-            <el-link type="primary" :href="file.url" target="_blank">
-              <i class="el-icon-document"></i> {{ file.name }}
-            </el-link>
-          </div>
-        </el-descriptions-item>
+
+        <el-descriptions-item label="鍒涘缓浜�">{{
+          currentRecord.createBy
+        }}</el-descriptions-item>
+        <el-descriptions-item label="鍒涘缓鏃堕棿">{{
+          formatDateTime(currentRecord.createTime)
+        }}</el-descriptions-item>
+        <el-descriptions-item label="鏇存柊浜�">{{
+          currentRecord.updateBy
+        }}</el-descriptions-item>
+        <el-descriptions-item label="鏇存柊鏃堕棿">{{
+          formatDateTime(currentRecord.updateTime)
+        }}</el-descriptions-item>
+        <el-descriptions-item label="澶囨敞" :span="2">{{
+          currentRecord.remark || "鏃�"
+        }}</el-descriptions-item>
       </el-descriptions>
+
       <span slot="footer">
         <el-button @click="detailDialogVisible = false">鍏抽棴</el-button>
-        <el-button type="primary" @click="handleEdit(currentRecord)">缂栬緫</el-button>
+        <el-button
+          type="primary"
+          @click="handleEdit(currentRecord.id)"
+          :disabled="currentRecord.delFlag === 1"
+        >
+          缂栬緫
+        </el-button>
       </span>
     </el-dialog>
 
@@ -227,35 +488,31 @@
           <el-input v-model="editForm.title" placeholder="璇疯緭鍏ヤ細璁富棰�" />
         </el-form-item>
 
-        <el-form-item label="浼氳绫诲瀷" prop="meetingType">
-          <el-select v-model="editForm.meetingType" placeholder="璇烽�夋嫨浼氳绫诲瀷" style="width: 100%">
-            <el-option label="绉戠爺浼氳" value="research" />
-            <el-option label="鏃ュ父浼氳" value="daily" />
-            <el-option label="椤圭洰浼氳" value="project" />
-            <el-option label="閮ㄩ棬浼氳" value="department" />
-            <el-option label="璇勫浼氳" value="review" />
-          </el-select>
-        </el-form-item>
-
-        <el-form-item label="鍙備細浜哄憳" prop="participants">
+        <el-form-item label="浼氳绫诲瀷" prop="typeId">
           <el-select
-            v-model="editForm.participants"
-            multiple
-            filterable
-            placeholder="璇烽�夋嫨鍙備細浜哄憳"
+            v-model="editForm.typeId"
+            placeholder="璇烽�夋嫨浼氳绫诲瀷"
             style="width: 100%"
           >
-            <el-option
-              v-for="user in userList"
-              :key="user.id"
-              :label="user.name"
-              :value="user.name"
-            />
+            <el-option label="绉戠爺浼氳" :value="1" />
+            <el-option label="鏃ュ父浼氳" :value="2" />
+            <el-option label="椤圭洰浼氳" :value="3" />
+            <el-option label="閮ㄩ棬浼氳" :value="4" />
+            <el-option label="璇勫浼氳" :value="5" />
           </el-select>
         </el-form-item>
 
-        <el-form-item label="浼氳鍦扮偣" prop="location">
-          <el-input v-model="editForm.location" placeholder="璇疯緭鍏ヤ細璁湴鐐�" />
+        <el-form-item label="浼氳鍦扮偣" prop="locationId">
+          <el-select
+            v-model="editForm.locationId"
+            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-select>
         </el-form-item>
 
         <el-row :gutter="20">
@@ -283,6 +540,19 @@
           </el-col>
         </el-row>
 
+        <el-form-item label="鎻愬墠鎻愰啋" prop="reminderMinutes">
+          <el-input-number
+            v-model="editForm.reminderMinutes"
+            :min="0"
+            :max="1440"
+            :step="5"
+            controls-position="right"
+            style="width: 100%"
+          >
+            <template #append>鍒嗛挓</template>
+          </el-input-number>
+        </el-form-item>
+
         <el-form-item label="浼氳姒傝" prop="summary">
           <el-input
             v-model="editForm.summary"
@@ -299,29 +569,106 @@
             v-model="editForm.content"
             type="textarea"
             :rows="6"
-            placeholder="璇疯緭鍏ヤ細璁叿浣撳唴瀹�"
+            placeholder="璇疯緭鍏ヤ細璁叿浣撳唴瀹癸紙鏀寔HTML鏍煎紡锛�"
           />
         </el-form-item>
 
-        <el-form-item label="闄勪欢涓婁紶">
-          <el-upload
-            action="#"
-            :auto-upload="false"
-            :on-change="handleFileChange"
-            :file-list="editForm.attachments"
-            :limit="5"
-            multiple
-          >
-            <el-button size="small" type="primary">鐐瑰嚮涓婁紶</el-button>
-            <div slot="tip" class="el-upload__tip">鏀寔涓婁紶鏂囨。銆佸浘鐗囩瓑鏂囦欢锛屽崟涓枃浠朵笉瓒呰繃10MB</div>
-          </el-upload>
+        <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"
+              >
+                <span class="file-name">{{ file.name }}</span>
+                <el-button
+                  type="text"
+                  size="mini"
+                  @click="handleRemoveAttachmentFile(index)"
+                  style="color: #F56C6C;"
+                >
+                  鍒犻櫎
+                </el-button>
+              </div>
+            </div>
+          </div>
+        </el-form-item>
+
+        <el-divider>浼氳绾锛堝彲浼氬悗琛ュ厖锛�</el-divider>
+
+        <el-form-item label="绾鍐呭" prop="recordcontent">
+          <el-input
+            v-model="editForm.recordcontent"
+            type="textarea"
+            :rows="6"
+            placeholder="璇疯緭鍏ヤ細璁邯瑕佸唴瀹癸紝鍖呮嫭浼氳鍐宠銆佽鍔ㄨ鍒掋�佽矗浠讳汉绛変俊鎭�"
+            maxlength="1000"
+            show-word-limit
+          />
+          <div style="color: #909399; font-size: 12px; margin-top: 4px;">
+            鎻愮ず锛氬彲璁板綍浼氳璁ㄨ瑕佺偣銆佸喅璁簨椤广�佽鍔ㄨ鍒掔瓑
+          </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
+            >
+              <el-button size="small" type="primary" icon="el-icon-upload">
+                涓婁紶绾闄勪欢
+              </el-button>
+              <div slot="tip" class="el-upload__tip">
+                鏀寔鍥剧墖銆佹枃妗g瓑鏍煎紡锛屽崟涓枃浠朵笉瓒呰繃10MB
+              </div>
+            </el-upload>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="澶囨敞" prop="remark">
+          <el-input
+            v-model="editForm.remark"
+            type="textarea"
+            :rows="2"
+            placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
+          />
         </el-form-item>
       </el-form>
 
       <span slot="footer">
         <el-button @click="handleEditClose">鍙栨秷</el-button>
         <el-button type="primary" @click="handleSave" :loading="saveLoading">
-          {{ isEditing ? '淇濆瓨' : '鏂板' }}
+          {{ isEditing ? "淇濆瓨" : "鏂板" }}
         </el-button>
       </span>
     </el-dialog>
@@ -329,20 +676,30 @@
 </template>
 
 <script>
+import {
+  meetinglist,
+  meetingedit,
+  meetingadd,
+  meetingInfo,
+  meetingDel,
+  exporremeeting
+} from "@/api/officeManagementApi";
+
 export default {
-  name: 'MeetingManagement',
+  name: "MeetingManagement",
   data() {
     return {
       // 鏌ヨ鍙傛暟
       queryParams: {
-        meetingType: '',
-        location: '',
+        title: "",
+        meetingType: "",
+        location: "",
         dateRange: [],
-        status: ''
+        status: ""
       },
       // 鍒嗛〉鍙傛暟
       pagination: {
-        currentPage: 1,
+        pageNum: 1,
         pageSize: 10,
         total: 0
       },
@@ -352,333 +709,541 @@
       // 瀵硅瘽妗嗘樉绀虹姸鎬�
       detailDialogVisible: false,
       editDialogVisible: false,
+      minutesDialogVisible: false,
       // 褰撳墠鎿嶄綔璁板綍
       currentRecord: {},
       // 缂栬緫鐘舵��
       isEditing: false,
       // 琛ㄦ牸鏁版嵁
       tableData: [],
-      // 鐢ㄦ埛鍒楄〃锛堢敤浜庨�夋嫨鍙備細浜哄憳锛�
-      userList: [
-        { id: 1, name: '寮犱笁' },
-        { id: 2, name: '鏉庡洓' },
-        { id: 3, name: '鐜嬩簲' },
-        { id: 4, name: '璧靛叚' },
-        { id: 5, name: '閽变竷' },
-        { id: 6, name: '瀛欏叓' },
-        { id: 7, name: '鍛ㄤ節' },
-        { id: 8, name: '鍚村崄' }
-      ],
       // 缂栬緫琛ㄥ崟鏁版嵁
-      editForm: {
-        title: '',
-        meetingType: '',
-        participants: [],
-        location: '',
-        startTime: '',
-        endTime: '',
-        summary: '',
-        content: '',
-        attachments: []
-      },
+      editForm: this.getDefaultFormData(),
       // 琛ㄥ崟楠岃瘉瑙勫垯
       editRules: {
-        title: [{ required: true, message: '璇疯緭鍏ヤ細璁富棰�', trigger: 'blur' }],
-        meetingType: [{ required: true, message: '璇烽�夋嫨浼氳绫诲瀷', trigger: 'change' }],
-        participants: [{ required: true, message: '璇烽�夋嫨鍙備細浜哄憳', trigger: 'change' }],
-        location: [{ required: true, message: '璇疯緭鍏ヤ細璁湴鐐�', trigger: 'blur' }],
-        startTime: [{ required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change' }],
-        endTime: [{ required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change' }],
-        summary: [{ required: true, message: '璇疯緭鍏ヤ細璁瑕�', trigger: 'blur' }],
-        content: [{ required: true, message: '璇疯緭鍏ヤ細璁唴瀹�', trigger: 'blur' }]
+        title: [{ required: true, message: "璇疯緭鍏ヤ細璁富棰�", trigger: "blur" }],
+        typeId: [
+          { required: true, message: "璇烽�夋嫨浼氳绫诲瀷", trigger: "change" }
+        ],
+        locationId: [
+          { required: true, message: "璇烽�夋嫨浼氳鍦扮偣", trigger: "change" }
+        ],
+        startTime: [
+          { required: true, message: "璇烽�夋嫨寮�濮嬫椂闂�", trigger: "change" }
+        ],
+        endTime: [
+          { required: true, message: "璇烽�夋嫨缁撴潫鏃堕棿", trigger: "change" }
+        ],
+        summary: [
+          { required: true, message: "璇疯緭鍏ヤ細璁瑕�", trigger: "blur" }
+        ],
+        content: [
+          { required: true, message: "璇疯緭鍏ヤ細璁唴瀹�", trigger: "blur" }
+        ],
+        reminderMinutes: [
+          { required: true, message: "璇疯緭鍏ユ彁鍓嶆彁閱掓椂闂�", trigger: "blur" }
+        ]
       }
-    }
+    };
   },
   mounted() {
-    this.loadData()
+    this.loadData();
   },
   methods: {
     // 鍔犺浇鏁版嵁
     async loadData() {
-      this.loading = true
+      this.loading = true;
       try {
-        // 妯℃嫙API璋冪敤
-        await new Promise(resolve => setTimeout(resolve, 500))
+        const params = {
+          pageNum: this.pagination.pageNum,
+          pageSize: this.pagination.pageSize,
+          ...this.queryParams
+        };
 
-        // 鐢熸垚妯℃嫙鏁版嵁
-        this.tableData = this.generateMockData()
-        this.pagination.total = this.tableData.length
+        // 澶勭悊鏃堕棿鑼冨洿鏌ヨ
+        if (
+          this.queryParams.dateRange &&
+          this.queryParams.dateRange.length === 2
+        ) {
+          params.startTime = this.queryParams.dateRange[0];
+          params.endTime = this.queryParams.dateRange[1];
+        }
+
+        const response = await meetinglist(params);
+
+        if (response.code === 200) {
+          this.tableData = response.rows || [];
+          this.pagination.total = response.total || 0;
+        } else {
+          this.$message.error(response.msg || "鑾峰彇鏁版嵁澶辫触");
+        }
       } catch (error) {
-        console.error('鍔犺浇鏁版嵁澶辫触:', error)
-        this.$message.error('鏁版嵁鍔犺浇澶辫触')
+        console.error("鍔犺浇鏁版嵁澶辫触:", error);
+        this.$message.error("鏁版嵁鍔犺浇澶辫触");
       } finally {
-        this.loading = false
+        this.loading = false;
       }
     },
 
-    // 鐢熸垚妯℃嫙鏁版嵁
-    generateMockData() {
-      const meetingTypes = ['research', 'daily', 'project', 'department', 'review']
-      const statuses = ['pending', 'ongoing', 'completed', 'cancelled']
-      const participantsPool = ['寮犱笁', '鏉庡洓', '鐜嬩簲', '璧靛叚', '閽变竷', '瀛欏叓', '鍛ㄤ節', '鍚村崄']
+    // 鑾峰彇鏂囦欢鍥炬爣
+    getFileIcon(fileName) {
+      if (!fileName) return "el-icon-document";
+      const ext = fileName
+        .split(".")
+        .pop()
+        .toLowerCase();
+      const iconMap = {
+        pdf: "el-icon-document",
+        doc: "el-icon-document",
+        docx: "el-icon-document",
+        xls: "el-icon-document",
+        xlsx: "el-icon-document",
+        ppt: "el-icon-document",
+        pptx: "el-icon-document",
+        jpg: "el-icon-picture",
+        jpeg: "el-icon-picture",
+        png: "el-icon-picture",
+        gif: "el-icon-picture",
+        zip: "el-icon-folder",
+        rar: "el-icon-folder"
+      };
+      return iconMap[ext] || "el-icon-document";
+    },
 
-      return Array.from({ length: 10 }, (_, index) => {
-        const participantCount = Math.floor(Math.random() * 5) + 2
-        const participants = []
-        for (let i = 0; i < participantCount; i++) {
-          const randomIndex = Math.floor(Math.random() * participantsPool.length)
-          participants.push(participantsPool[randomIndex])
+    // 鏌ョ湅浼氳绾
+    handleViewMinutes(record) {
+      this.currentRecord = { ...record };
+      this.minutesDialogVisible = true;
+    },
+
+    // 瑙f瀽闄勪欢JSON
+    parseAttachments(attachmentJson) {
+      if (!attachmentJson) return [];
+      try {
+        if (typeof attachmentJson === "string") {
+          return JSON.parse(attachmentJson);
         }
-
-        // 鍘婚噸
-        const uniqueParticipants = [...new Set(participants)]
-
-        const startTime = new Date()
-        startTime.setDate(startTime.getDate() + Math.floor(Math.random() * 30) - 15)
-        startTime.setHours(9 + Math.floor(Math.random() * 8), Math.floor(Math.random() * 4) * 15, 0)
-
-        const endTime = new Date(startTime)
-        endTime.setHours(startTime.getHours() + Math.floor(Math.random() * 3) + 1)
-
-        return {
-          id: index + 1,
-          title: `鍏充簬${['绉戠爺椤圭洰', '鏃ュ父宸ヤ綔', '鎶�鏈瘎瀹�', '閮ㄩ棬鍗忚皟'][Math.floor(Math.random() * 4)]}鐨勪細璁甡,
-          meetingType: meetingTypes[Math.floor(Math.random() * meetingTypes.length)],
-          participants: uniqueParticipants,
-          location: ['绗竴浼氳瀹�', '绗簩浼氳瀹�', '绗笁浼氳瀹�', '绾夸笂浼氳'][Math.floor(Math.random() * 4)],
-          startTime: startTime.toISOString(),
-          endTime: endTime.toISOString(),
-          summary: `鏈浼氳涓昏璁ㄨ${['椤圭洰杩涘睍', '鎶�鏈毦棰�', '宸ヤ綔璁″垝', '闂鍗忚皟'][Math.floor(Math.random() * 4)]}绛夌浉鍏充簨瀹渀,
-          content: `浼氳璇︾粏鍐呭锛歕n1. 璁涓�璁ㄨ\n2. 璁浜屽垎鏋怽n3. 涓嬩竴姝ュ伐浣滆鍒抃n4. 浠诲姟鍒嗛厤`,
-          status: statuses[Math.floor(Math.random() * statuses.length)],
-          creator: '绯荤粺绠$悊鍛�',
-          attachments: []
-        }
-      })
+        return attachmentJson;
+      } catch (error) {
+        console.error("瑙f瀽闄勪欢澶辫触:", error);
+        return [];
+      }
     },
 
     // 鑾峰彇浼氳绫诲瀷鏍囩鏍峰紡
-    getMeetingTypeTag(type) {
+    getMeetingTypeTag(typeId) {
       const typeMap = {
-        research: 'primary',
-        daily: 'success',
-        project: 'warning',
-        department: 'info',
-        review: 'danger'
-      }
-      return typeMap[type] || 'info'
+        1: "primary", // 绉戠爺浼氳
+        2: "success", // 鏃ュ父浼氳
+        3: "warning", // 椤圭洰浼氳
+        4: "info", // 閮ㄩ棬浼氳
+        5: "danger" // 璇勫浼氳
+      };
+      return typeMap[typeId] || "info";
     },
 
     // 鑾峰彇浼氳绫诲瀷鏂囨湰
-    getMeetingTypeText(type) {
+    getMeetingTypeText(typeId) {
       const textMap = {
-        research: '绉戠爺浼氳',
-        daily: '鏃ュ父浼氳',
-        project: '椤圭洰浼氳',
-        department: '閮ㄩ棬浼氳',
-        review: '璇勫浼氳'
-      }
-      return textMap[type] || type
+        1: "绉戠爺浼氳",
+        2: "鏃ュ父浼氳",
+        3: "椤圭洰浼氳",
+        4: "閮ㄩ棬浼氳",
+        5: "璇勫浼氳"
+      };
+      return textMap[typeId] || "鍏朵粬";
     },
 
-    // 鑾峰彇鐘舵�佹爣绛炬牱寮�
-    getStatusTag(status) {
+    // 鑾峰彇浼氳鐘舵�佹爣绛炬牱寮�
+    getMeetingStatusTag(status) {
       const statusMap = {
-        pending: 'primary',
-        ongoing: 'success',
-        completed: 'info',
-        cancelled: 'danger'
-      }
-      return statusMap[status] || 'info'
+        1: "primary", // 寰呭紑濮�
+        2: "success", // 杩涜涓�
+        3: "info", // 宸茬粨鏉�
+        4: "danger" // 宸插彇娑�
+      };
+      return statusMap[status] || "info";
     },
 
-    // 鑾峰彇鐘舵�佹枃鏈�
-    getStatusText(status) {
+    // 鑾峰彇浼氳鐘舵�佹枃鏈�
+    getMeetingStatusText(status) {
       const textMap = {
-        pending: '寰呭紑濮�',
-        ongoing: '杩涜涓�',
-        completed: '宸茬粨鏉�',
-        cancelled: '宸插彇娑�'
-      }
-      return textMap[status] || status
+        1: "寰呭紑濮�",
+        2: "杩涜涓�",
+        3: "宸茬粨鏉�",
+        4: "宸插彇娑�"
+      };
+      return textMap[status] || "鏈煡";
+    },
+
+    // 鑾峰彇瀹℃牳鐘舵�佹爣绛炬牱寮�
+    getApprovalStatusTag(status) {
+      const statusMap = {
+        0: "warning", // 寰呭鏍�
+        1: "success", // 宸查�氳繃
+        2: "danger" // 宸查┏鍥�
+      };
+      return statusMap[status] || "info";
+    },
+
+    // 鑾峰彇瀹℃牳鐘舵�佹枃鏈�
+    getApprovalStatusText(status) {
+      const textMap = {
+        0: "寰呭鏍�",
+        1: "宸查�氳繃",
+        2: "宸查┏鍥�"
+      };
+      return textMap[status] || "鏈鏍�";
     },
 
     // 鏍煎紡鍖栨棩鏈熸椂闂�
     formatDateTime(dateTime) {
-      if (!dateTime) return ''
-      const date = new Date(dateTime)
-      return date.toLocaleString('zh-CN')
+      if (!dateTime) return "";
+      return dateTime.replace("T", " ");
     },
 
     // 璁$畻浼氳鎸佺画鏃堕棿
     calculateDuration(record) {
-      if (!record.startTime || !record.endTime) return ''
-      const start = new Date(record.startTime)
-      const end = new Date(record.endTime)
-      const duration = (end - start) / (1000 * 60) // 鍒嗛挓鏁�
+      if (!record.startTime || !record.endTime) return "";
+      const start = new Date(record.startTime);
+      const end = new Date(record.endTime);
+      const duration = (end - start) / (1000 * 60); // 鍒嗛挓鏁�
 
       if (duration < 60) {
-        return `${Math.round(duration)}鍒嗛挓`
+        return `${Math.round(duration)}鍒嗛挓`;
       } else {
-        const hours = Math.floor(duration / 60)
-        const minutes = Math.round(duration % 60)
-        return minutes > 0 ? `${hours}灏忔椂${minutes}鍒嗛挓` : `${hours}灏忔椂`
+        const hours = Math.floor(duration / 60);
+        const minutes = Math.round(duration % 60);
+        return minutes > 0 ? `${hours}灏忔椂${minutes}鍒嗛挓` : `${hours}灏忔椂`;
       }
+    },
+
+    // 鏍煎紡鍖栨枃浠跺ぇ灏�
+    formatFileSize(bytes) {
+      if (!bytes) return "0 B";
+      const k = 1024;
+      const sizes = ["B", "KB", "MB", "GB"];
+      const i = Math.floor(Math.log(bytes) / Math.log(k));
+      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
     },
 
     // 鏌ヨ澶勭悊
     handleQuery() {
-      this.pagination.currentPage = 1
-      this.loadData()
+      this.pagination.pageNum = 1;
+      this.loadData();
     },
 
     // 閲嶇疆鏌ヨ
     handleReset() {
       this.queryParams = {
-        meetingType: '',
-        location: '',
+        title: "",
+        meetingType: "",
+        location: "",
         dateRange: [],
-        status: ''
-      }
-      this.pagination.currentPage = 1
-      this.loadData()
+        status: ""
+      };
+      this.pagination.pageNum = 1;
+      this.loadData();
     },
 
     // 鏌ョ湅璇︽儏
-    handleView(record) {
-      this.currentRecord = { ...record }
-      this.detailDialogVisible = true
+    async handleView(id) {
+      try {
+        const response = await meetingInfo(id);
+        if (response.code === 200) {
+          this.currentRecord = response.data || {};
+          this.detailDialogVisible = true;
+        } else {
+          this.$message.error(response.msg || "鑾峰彇璇︽儏澶辫触");
+        }
+      } catch (error) {
+        console.error("鑾峰彇璇︽儏澶辫触:", error);
+        this.$message.error("鑾峰彇璇︽儏澶辫触");
+      }
     },
 
     // 鏂板璁板綍
     handleAdd() {
-      this.isEditing = false
-      this.editForm = this.getDefaultFormData()
-      this.editDialogVisible = true
+      this.isEditing = false;
+      this.editForm = this.getDefaultFormData();
+      this.editDialogVisible = true;
       this.$nextTick(() => {
-        this.$refs.editForm && this.$refs.editForm.clearValidate()
-      })
+        this.$refs.editForm && this.$refs.editForm.clearValidate();
+      });
     },
 
     // 缂栬緫璁板綍
-    handleEdit(record) {
-      this.isEditing = true
-      this.currentRecord = record
-      this.editForm = { ...record }
-      this.editDialogVisible = true
-      this.detailDialogVisible = false
-      this.$nextTick(() => {
-        this.$refs.editForm && this.$refs.editForm.clearValidate()
-      })
+    async handleEdit(id) {
+      try {
+        const response = await meetingInfo(id);
+        if (response.code === 200) {
+          this.isEditing = true;
+          this.currentRecord = response.data || {};
+          this.editForm = { ...response.data };
+
+          // 瑙f瀽闄勪欢
+          if (this.editForm.attachment) {
+            this.editForm.attachmentFiles = this.parseAttachments(
+              this.editForm.attachment
+            );
+          }
+          if (this.editForm.recordattachment) {
+            this.editForm.recordattachmentFiles = this.parseAttachments(
+              this.editForm.recordattachment
+            );
+          }
+
+          this.editDialogVisible = true;
+          this.detailDialogVisible = false;
+          this.$nextTick(() => {
+            this.$refs.editForm && this.$refs.editForm.clearValidate();
+          });
+        } else {
+          this.$message.error(response.msg || "鑾峰彇璁板綍澶辫触");
+        }
+      } catch (error) {
+        console.error("鑾峰彇璁板綍澶辫触:", error);
+        this.$message.error("鑾峰彇璁板綍澶辫触");
+      }
     },
 
     // 澶嶅埗璁板綍
-    handleCopy(record) {
-      this.isEditing = false
-      const copiedRecord = { ...record }
-      delete copiedRecord.id
-      copiedRecord.title = copiedRecord.title + '锛堝鍒讹級'
-      this.editForm = copiedRecord
-      this.editDialogVisible = true
-      this.$nextTick(() => {
-        this.$refs.editForm && this.$refs.editForm.clearValidate()
-      })
+    async handleCopy(id) {
+      try {
+        const response = await meetingInfo(id);
+        if (response.code === 200) {
+          this.isEditing = false;
+          const copiedRecord = { ...response.data };
+
+          // 绉婚櫎ID锛岀敓鎴愭柊璁板綍
+          delete copiedRecord.id;
+          delete copiedRecord.meetingNumber;
+          copiedRecord.title = copiedRecord.title + "锛堝鍒讹級";
+          copiedRecord.parentMeetingId = id;
+
+          // 瑙f瀽闄勪欢
+          if (copiedRecord.attachment) {
+            copiedRecord.attachmentFiles = this.parseAttachments(
+              copiedRecord.attachment
+            );
+          }
+          if (copiedRecord.recordattachment) {
+            copiedRecord.recordattachmentFiles = this.parseAttachments(
+              copiedRecord.recordattachment
+            );
+          }
+
+          this.editForm = copiedRecord;
+          this.editDialogVisible = true;
+          this.$nextTick(() => {
+            this.$refs.editForm && this.$refs.editForm.clearValidate();
+          });
+        } else {
+          this.$message.error(response.msg || "鑾峰彇璁板綍澶辫触");
+        }
+      } catch (error) {
+        console.error("鑾峰彇璁板綍澶辫触:", error);
+        this.$message.error("鑾峰彇璁板綍澶辫触");
+      }
     },
 
     // 鍒犻櫎璁板綍
-    handleDelete(record) {
-      this.$confirm('纭畾瑕佸垹闄よ繖鏉′細璁褰曞悧锛�', '鎻愮ず', {
-        confirmButtonText: '纭畾',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning'
-      }).then(() => {
-        // 妯℃嫙鍒犻櫎鎿嶄綔
-        this.tableData = this.tableData.filter(item => item.id !== record.id)
-        this.pagination.total = this.tableData.length
-        this.$message.success('鍒犻櫎鎴愬姛')
-      }).catch(() => {})
+    async handleDelete(record) {
+      try {
+        await this.$confirm("纭畾瑕佸垹闄よ繖鏉′細璁褰曞悧锛�", "鎻愮ず", {
+          confirmButtonText: "纭畾",
+          cancelButtonText: "鍙栨秷",
+          type: "warning"
+        });
+
+        const response = await meetingDel(record.id);
+        if (response.code === 200) {
+          this.$message.success("鍒犻櫎鎴愬姛");
+          this.loadData();
+        } else {
+          this.$message.error(response.msg || "鍒犻櫎澶辫触");
+        }
+      } catch (error) {
+        if (error !== "cancel") {
+          console.error("鍒犻櫎澶辫触:", error);
+          this.$message.error("鍒犻櫎澶辫触");
+        }
+      }
+    },
+
+    // 鏂囦欢涓婁紶澶勭悊
+    handleAttachmentChange(file, fileList) {
+      this.editForm.attachmentFiles = fileList;
+    },
+
+    handleMinutesAttachmentChange(file, fileList) {
+      this.editForm.recordattachmentFiles = fileList;
+    },
+
+    // 鍒犻櫎宸蹭笂浼犵殑鏂囦欢
+    handleRemoveAttachmentFile(index) {
+      this.editForm.attachmentFiles.splice(index, 1);
+    },
+
+    // 鏂囦欢涓嬭浇
+    handleDownload(file) {
+      if (file.url) {
+        const link = document.createElement("a");
+        link.href = file.url;
+        link.download = file.name;
+        link.click();
+        this.$message.success(`寮�濮嬩笅杞�: ${file.name}`);
+      } else {
+        this.$message.warning("鏂囦欢鍦板潃涓嶅瓨鍦�");
+      }
     },
 
     // 淇濆瓨璁板綍
     async handleSave() {
       try {
-        const valid = await this.$refs.editForm.validate()
-        if (!valid) return
+        const valid = await this.$refs.editForm.validate();
+        if (!valid) return;
 
-        this.saveLoading = true
-        // 妯℃嫙API璋冪敤
-        await new Promise(resolve => setTimeout(resolve, 1000))
+        // 楠岃瘉鏃堕棿
+        if (this.editForm.startTime && this.editForm.endTime) {
+          if (
+            new Date(this.editForm.endTime) <= new Date(this.editForm.startTime)
+          ) {
+            this.$message.error("缁撴潫鏃堕棿蹇呴』鏅氫簬寮�濮嬫椂闂�");
+            return;
+          }
+        }
 
-        this.$message.success(this.isEditing ? '淇濆瓨鎴愬姛' : '鏂板鎴愬姛')
-        this.editDialogVisible = false
-        this.loadData()
+        this.saveLoading = true;
+
+        // 澶勭悊闄勪欢
+        const formData = { ...this.editForm };
+
+        if (formData.attachmentFiles) {
+          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()
+            }))
+          );
+        }
+
+        if (formData.recordattachmentFiles) {
+          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()
+            }))
+          );
+        }
+
+        // 娓呯悊鏂囦欢鍒楄〃瀛楁
+        delete formData.attachmentFiles;
+        delete formData.recordattachmentFiles;
+
+        let response;
+        if (this.isEditing) {
+          response = await meetingedit(formData);
+        } else {
+          response = await meetingadd(formData);
+        }
+
+        if (response.code === 200) {
+          this.$message.success(this.isEditing ? "淇濆瓨鎴愬姛" : "鏂板鎴愬姛");
+          this.editDialogVisible = false;
+          this.loadData();
+        } else {
+          this.$message.error(
+            response.msg || (this.isEditing ? "淇濆瓨澶辫触" : "鏂板澶辫触")
+          );
+        }
       } catch (error) {
-        console.error('淇濆瓨澶辫触:', error)
-        this.$message.error('鎿嶄綔澶辫触')
+        console.error("淇濆瓨澶辫触:", error);
+        this.$message.error(this.isEditing ? "淇濆瓨澶辫触" : "鏂板澶辫触");
       } finally {
-        this.saveLoading = false
+        this.saveLoading = false;
       }
-    },
-
-    // 鏂囦欢涓婁紶澶勭悊
-    handleFileChange(file, fileList) {
-      this.editForm.attachments = fileList
     },
 
     // 鍏抽棴璇︽儏瀵硅瘽妗�
     handleDetailClose() {
-      this.detailDialogVisible = false
-      this.currentRecord = {}
+      this.detailDialogVisible = false;
+      this.currentRecord = {};
     },
 
     // 鍏抽棴缂栬緫瀵硅瘽妗�
     handleEditClose() {
-      this.editDialogVisible = false
-      this.currentRecord = {}
+      this.editDialogVisible = false;
+      this.currentRecord = {};
+      this.editForm = this.getDefaultFormData();
       this.$nextTick(() => {
-        this.$refs.editForm && this.$refs.editForm.clearValidate()
-      })
+        this.$refs.editForm && this.$refs.editForm.clearValidate();
+      });
     },
 
     // 瀵煎嚭鏁版嵁
     exportData() {
-      this.$message.success('瀵煎嚭鍔熻兘寮�鍙戜腑')
+      const queryParams = this.queryParams;
+      this.$modal
+        .confirm("鏄惁纭瀵煎嚭鎵�鏈変細璁邯瑕佹暟鎹」锛�")
+        .then(() => {
+          return exporremeeting(queryParams);
+        })
+        .then(response => {
+          this.$download.name(response.msg);
+        })
+        .catch(() => {});
     },
 
     // 鍒嗛〉澶у皬鍙樺寲
     handleSizeChange(size) {
-      this.pagination.pageSize = size
-      this.pagination.currentPage = 1
-      this.loadData()
+      this.pagination.pageSize = size;
+      this.pagination.pageNum = 1;
+      this.loadData();
     },
 
     // 褰撳墠椤靛彉鍖�
     handleCurrentChange(page) {
-      this.pagination.currentPage = page
-      this.loadData()
+      this.pagination.pageNum = page;
+      this.loadData();
     },
 
     // 鎺掑簭鍙樺寲
     handleSortChange(sort) {
-      console.log('鎺掑簭鍙樺寲:', sort)
+      console.log("鎺掑簭鍙樺寲:", sort);
     },
 
     // 鑾峰彇榛樿琛ㄥ崟鏁版嵁
     getDefaultFormData() {
       return {
-        title: '',
-        meetingType: '',
-        participants: [],
-        location: '',
-        startTime: '',
-        endTime: '',
-        summary: '',
-        content: '',
-        attachments: []
-      }
+        id: null,
+        title: "",
+        typeId: null,
+        locationId: null,
+        startTime: "",
+        endTime: "",
+        summary: "",
+        content: "",
+        attachment: null,
+        attachmentFiles: [],
+        status: 1, // 榛樿寰呭紑濮�
+        isRecurring: 0,
+        recurringPattern: null,
+        parentMeetingId: null,
+        reminderMinutes: 30,
+        recordcontent: "",
+        recordattachment: null,
+        recordattachmentFiles: [],
+        recorderBy: "",
+        remark: "",
+        approvalStatus: 0 // 榛樿寰呭鏍�
+      };
     }
   }
-}
+};
 </script>
 
 <style scoped>
@@ -711,7 +1276,21 @@
 .attachment-item {
   margin-bottom: 8px;
 }
+.minutes-content {
+  margin-bottom: 16px;
+}
 
+.minutes-meta {
+  border-top: 1px solid #e4e7ed;
+  padding-top: 12px;
+}
+
+/* 鍝嶅簲寮忚皟鏁� */
+@media (max-width: 768px) {
+  .minutes-content .el-card {
+    margin: 0 -20px;
+  }
+}
 /* 鍝嶅簲寮忚璁� */
 @media (max-width: 768px) {
   .page-header {
@@ -725,4 +1304,115 @@
     justify-content: space-between;
   }
 }
+/* 鏂板闄勪欢鐩稿叧鏍峰紡 */
+.attachment-upload-section {
+  border: 1px solid #ebeef5;
+  border-radius: 4px;
+  padding: 15px;
+  background-color: #fafafa;
+}
+
+.section-title {
+  font-weight: bold;
+  margin-bottom: 8px;
+  color: #303133;
+}
+
+.upload-tip {
+  font-size: 12px;
+  color: #909399;
+  margin-bottom: 10px;
+}
+
+.uploaded-files {
+  margin-top: 10px;
+}
+
+.file-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 8px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.file-item:last-child {
+  border-bottom: none;
+}
+
+.file-name {
+  flex: 1;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.attachment-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+  gap: 10px;
+}
+
+.file-card {
+  transition: all 0.3s ease;
+}
+
+.file-card:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+}
+
+.file-content {
+  display: flex;
+  align-items: center;
+}
+
+.file-icon {
+  font-size: 24px;
+  color: #409eff;
+  margin-right: 10px;
+}
+
+.file-info {
+  flex: 1;
+}
+
+.file-name {
+  font-size: 14px;
+  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: center;
+}
+
+.file-link {
+  display: flex;
+  align-items: center;
+}
+
+.no-attachment {
+  text-align: center;
+  padding: 20px;
+  color: #909399;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+  .attachment-grid {
+    grid-template-columns: 1fr;
+  }
+}
 </style>

--
Gitblit v1.9.3