WXL
2025-12-29 cd574e3394883b79eac5d63f3b11bca852dbc7a0
src/views/OfficeRelated/conference/index.vue
@@ -222,10 +222,11 @@
        />
      </div>
    </el-card>
    <el-dialog
      title="会议纪要"
      :visible.sync="minutesDialogVisible"
      width="600px"
      width="700px"
    >
      <div v-if="currentRecord.meetingMinutes">
        <el-alert
@@ -237,12 +238,45 @@
        <div class="minutes-content">
          <el-card>
            <div
              style="white-space: pre-line; line-height: 1.6; max-height: 400px; overflow-y: auto;"
              style="white-space: pre-line; line-height: 1.6; max-height: 300px; overflow-y: auto;"
            >
              {{ currentRecord.meetingMinutes }}
            </div>
          </el-card>
        </div>
        <!-- 会议纪要附件展示 -->
        <div
          class="minutes-attachments"
          v-if="
            currentRecord.minutesAttachments &&
              currentRecord.minutesAttachments.length > 0
          "
        >
          <el-divider content-position="left">会议纪要附件</el-divider>
          <div class="attachment-list">
            <div
              v-for="file in currentRecord.minutesAttachments"
              :key="file.id"
              class="attachment-item"
            >
              <el-link
                type="primary"
                :href="file.url"
                target="_blank"
                class="file-link"
              >
                <i
                  :class="getFileIcon(file.type)"
                  style="margin-right: 8px;"
                ></i>
                {{ file.name }}
                <span class="file-size">({{ formatFileSize(file.size) }})</span>
              </el-link>
            </div>
          </div>
        </div>
        <div
          class="minutes-meta"
          style="margin-top: 16px; color: #909399; font-size: 12px;"
@@ -327,19 +361,101 @@
            {{ currentRecord.content }}
          </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>
        <el-descriptions-item label="会议详情附件" :span="2">
          <div class="detail-attachments">
            <div
              v-if="
                currentRecord.detailAttachments &&
                  currentRecord.detailAttachments.length > 0
              "
              class="attachment-grid"
            >
              <div
                v-for="file in currentRecord.detailAttachments"
                :key="file.id"
                class="attachment-card"
              >
                <el-card shadow="hover" class="file-card">
                  <div class="file-content">
                    <i :class="getFileIcon(file.type)" 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">{{
                          formatFileSize(file.size)
                        }}</span>
                        <span class="file-time">{{
                          formatDateTime(file.uploadTime)
                        }}</span>
                      </div>
                    </div>
                  </div>
                  <div class="file-actions">
                    <el-button
                      type="text"
                      size="mini"
                      @click="handlePreview(file)"
                      >预览</el-button
                    >
                    <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">
          <div class="summary-attachments">
            <div
              v-if="
                currentRecord.summaryAttachments &&
                  currentRecord.summaryAttachments.length > 0
              "
              class="attachment-list"
            >
              <div
                v-for="file in currentRecord.summaryAttachments"
                :key="file.id"
                class="attachment-item"
              >
                <el-link
                  type="primary"
                  :href="file.url"
                  target="_blank"
                  class="file-link"
                >
                  <i
                    :class="getFileIcon(file.type)"
                    style="margin-right: 8px;"
                  ></i>
                  {{ file.name }}
                  <span class="file-size"
                    >({{ formatFileSize(file.size) }})</span
                  >
                </el-link>
              </div>
            </div>
            <div v-else class="no-attachment">
              <el-empty
                description="暂无会议概要附件"
                :image-size="50"
              ></el-empty>
            </div>
          </div>
        </el-descriptions-item>
      </el-descriptions>
@@ -404,7 +520,109 @@
        <el-form-item label="会议地点" prop="location">
          <el-input v-model="editForm.location" placeholder="请输入会议地点" />
        </el-form-item>
        <el-form-item label="会议详情附件">
          <div class="attachment-upload-section">
            <div class="section-title">会议相关资料</div>
            <div class="upload-tip">上传会议讨论材料、背景资料等相关文件</div>
            <el-upload
              class="detail-upload"
              action="#"
              :auto-upload="false"
              :on-change="handleDetailFileChange"
              :file-list="editForm.detailAttachments"
              :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.detailAttachments &&
                  editForm.detailAttachments.length > 0
              "
              class="uploaded-files"
            >
              <div
                v-for="(file, index) in editForm.detailAttachments"
                :key="file.uid || index"
                class="file-item"
              >
                <span class="file-name">{{ file.name }}</span>
                <el-button
                  type="text"
                  size="mini"
                  @click="handleRemoveDetailFile(index)"
                  style="color: #F56C6C;"
                >
                  删除
                </el-button>
              </div>
            </div>
          </div>
        </el-form-item>
        <el-form-item label="会议概要" prop="summary">
          <el-input
            v-model="editForm.summary"
            type="textarea"
            :rows="2"
            placeholder="请输入会议概要"
            maxlength="200"
            show-word-limit
          />
        </el-form-item>
        <!-- 会议概要附件上传 -->
        <el-form-item label="会议概要附件">
          <div class="attachment-upload-section">
            <div class="section-title">会议纪要材料</div>
            <div class="upload-tip">上传会议纪要、决议文件等相关材料</div>
            <el-upload
              class="summary-upload"
              action="#"
              :auto-upload="false"
              :on-change="handleSummaryFileChange"
              :file-list="editForm.summaryAttachments"
              :limit="5"
              multiple
            >
              <el-button size="small" type="primary" icon="el-icon-upload">
                上传概要附件
              </el-button>
              <div slot="tip" class="el-upload__tip">
                支持PDF、Word等文档格式,单个文件不超过10MB
              </div>
            </el-upload>
            <div
              v-if="
                editForm.summaryAttachments &&
                  editForm.summaryAttachments.length > 0
              "
              class="uploaded-files"
            >
              <div
                v-for="(file, index) in editForm.summaryAttachments"
                :key="file.uid || index"
                class="file-item"
              >
                <span class="file-name">{{ file.name }}</span>
                <el-button
                  type="text"
                  size="mini"
                  @click="handleRemoveSummaryFile(index)"
                  style="color: #F56C6C;"
                >
                  删除
                </el-button>
              </div>
            </div>
          </div>
        </el-form-item>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="开始时间" prop="startTime">
@@ -450,20 +668,27 @@
          />
        </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="minutes-upload"
              action="#"
              :auto-upload="false"
              :on-change="handleMinutesFileChange"
              :file-list="editForm.minutesAttachments"
              :limit="5"
              multiple
            >
              <el-button size="small" type="primary" icon="el-icon-upload">
                上传纪要附件
              </el-button>
              <div slot="tip" class="el-upload__tip">
                支持图片、文档等格式,单个文件不超过10MB
              </div>
            </el-upload>
          </div>
        </el-form-item>
        <el-form-item label="会议纪要" prop="meetingMinutes">
          <el-input
@@ -543,7 +768,10 @@
        endTime: "",
        summary: "",
        content: "",
        attachments: []
        attachments: [],
        detailAttachments: [], // 会议详情附件
        summaryAttachments: [], // 会议概要附件
        minutesAttachments: [] // 会议纪要附件
      },
      // 表单验证规则
      editRules: {
@@ -599,6 +827,24 @@
      } finally {
        this.loading = false;
      }
    },
    getFileIcon(fileType) {
      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[fileType] || "el-icon-document";
    },
    // 查看会议纪要
    handleViewMinutes(record) {
@@ -691,7 +937,9 @@
        const meetingMinutes = hasMinutes
          ? minutesExamples[Math.floor(Math.random() * minutesExamples.length)]
          : "";
        const hasDetailAttachments = Math.random() > 0.5;
        const hasSummaryAttachments = Math.random() > 0.6;
        const hasMinutesAttachments = Math.random() > 0.7;
        return {
          id: index + 1,
          title: `关于${
@@ -699,6 +947,47 @@
              Math.floor(Math.random() * 4)
            ]
          }的会议`,
           // 添加分类型附件
          detailAttachments: hasDetailAttachments ? [
            {
              id: `detail-${index}-1`,
              name: `会议材料-${index}.pdf`,
              type: 'pdf',
              size: 2048000,
              url: '/api/files/meeting-material.pdf',
              uploadTime: new Date(startTime.getTime() - 3600000).toISOString()
            },
            {
              id: `detail-${index}-2`,
              name: `背景资料-${index}.docx`,
              type: 'docx',
              size: 1024000,
              url: '/api/files/background.docx',
              uploadTime: new Date(startTime.getTime() - 7200000).toISOString()
            }
          ] : [],
          summaryAttachments: hasSummaryAttachments ? [
            {
              id: `summary-${index}-1`,
              name: `会议纪要-${index}.pdf`,
              type: 'pdf',
              size: 512000,
              url: '/api/files/meeting-summary.pdf',
              uploadTime: new Date(startTime.getTime() + 3600000).toISOString()
            }
          ] : [],
          minutesAttachments: hasMinutesAttachments ? [
            {
              id: `minutes-${index}-1`,
              name: `补充材料-${index}.jpg`,
              type: 'jpg',
              size: 1024000,
              url: '/api/files/supplement.jpg',
              uploadTime: new Date(startTime.getTime() + 7200000).toISOString()
            }
          ] : [],
          meetingType:
            meetingTypes[Math.floor(Math.random() * meetingTypes.length)],
          participants: uniqueParticipants,
@@ -868,7 +1157,51 @@
        })
        .catch(() => {});
    },
    // 新增方法:格式化文件大小
    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];
    },
    // 分类型文件上传处理
    handleDetailFileChange(file, fileList) {
      this.editForm.detailAttachments = fileList;
    },
    handleSummaryFileChange(file, fileList) {
      this.editForm.summaryAttachments = fileList;
    },
    handleMinutesFileChange(file, fileList) {
      this.editForm.minutesAttachments = fileList;
    },
    // 删除已上传的文件
    handleRemoveDetailFile(index) {
      this.editForm.detailAttachments.splice(index, 1);
    },
    handleRemoveSummaryFile(index) {
      this.editForm.summaryAttachments.splice(index, 1);
    },
    // 文件预览和下载
    handlePreview(file) {
      // 实现文件预览逻辑
      this.$message.info(`预览文件: ${file.name}`);
    },
    handleDownload(file) {
      // 实现文件下载逻辑
      const link = document.createElement("a");
      link.href = file.url;
      link.download = file.name;
      link.click();
      this.$message.success(`开始下载: ${file.name}`);
    },
    // 保存记录
    async handleSave() {
      try {
@@ -947,7 +1280,9 @@
        meetingMinutes: "",
        minutesCreateTime: "",
        minutesCreator: "",
        attachments: []
        detailAttachments: [],
        summaryAttachments: [],
        minutesAttachments: []
      };
    }
  }
@@ -1019,4 +1354,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>