WXL
4 天以前 87e331767b3ce416c957b7336e94b9ba208f0efb
维护
已修改8个文件
1718 ■■■■ 文件已修改
src/api/officeManagementApi/checkingIn.js 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/officeManagementApi/conference.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/officeManagementApi/index.js 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/officeManagementApi/studies.js 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/OfficeRelated/conference/index.vue 1164 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/OfficeRelated/engage/index.vue 429 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/affirm/affirmInfo.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/affirm/index.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/officeManagementApi/checkingIn.js
@@ -1,25 +1,40 @@
import request from '@/utils/request'
// 案例列表及详情
export function meetinglist(data) {
// 考勤列表
export function attendancerecordslist(data) {
  return request({
    url: '/project/meeting/list',
    url: '/project/attendancerecords/list',
    method: 'post',
    data: data
  })
}
// 考勤修改
export function meetingedit(data) {
export function attendancerecordsedit(data) {
  return request({
    url: '/project/meeting/edit',
    url: '/project/attendancerecords/edit',
    method: 'post',
    data: data
  })
}
// 考勤修改
export function attendancerecordsadd(data) {
  return request({
    url: '/project/attendancerecords/add',
    method: 'post',
    data: data
  })
}
// 考勤详情
export function meetingInfo(id) {
export function attendancerecordsInfo(id) {
  return request({
    url: '/project/meeting/getInfo/' + id,
    url: '/project/attendancerecords/getInfo/' + id,
    method: 'get'
  })
}
// 删除
export function attendancerecordsDel(id) {
  return request({
    url: '/project/attendancerecords/remove/' + id,
    method: 'get'
  })
}
src/api/officeManagementApi/conference.js
@@ -1,6 +1,6 @@
import request from '@/utils/request'
// 案例列表及详情
// 会议列表
export function meetinglist(data) {
  return request({
    url: '/project/meeting/list',
@@ -16,6 +16,14 @@
    data: data
  })
}
// 会议纪要修改
export function meetingadd(data) {
  return request({
    url: '/project/meeting/add',
    method: 'post',
    data: data
  })
}
// 会议纪要详情
export function meetingInfo(id) {
  return request({
@@ -23,3 +31,18 @@
    method: 'get'
  })
}
// 删除
export function meetingDel(id) {
  return request({
    url: '/project/meeting/remove/' + id,
    method: 'get'
  })
}
// 导出捐献器官管理
export function exporremeeting(query) {
  return request({
    url: '/project/meeting/export',
    method: 'get',
    params: query
  })
}
src/api/officeManagementApi/index.js
@@ -1,11 +1,4 @@
export * from "./affirm";
export * from "./allocation";
export * from "./appear";
export * from "./assess";
export * from "./course";
export * from "./ethicalReview";
export * from "./decide";
export * from "./GetWitness";
export * from "./maintain";
export * from "./OrganUtilization";
export * from "./transfer";
export * from "./studies";
export * from "./conference";
export * from "./checkingIn";
src/api/officeManagementApi/studies.js
@@ -1,25 +1,48 @@
import request from '@/utils/request'
// 案例列表及详情
export function meetinglist(data) {
// 进修列表
export function recordslist(data) {
  return request({
    url: '/project/meeting/list',
    url: '/project/records/list',
    method: 'post',
    data: data
  })
}
// 进修修改
export function meetingedit(data) {
export function recordsedit(data) {
  return request({
    url: '/project/meeting/edit',
    url: '/project/records/edit',
    method: 'post',
    data: data
  })
}
// 进修修改
export function recordsadd(data) {
  return request({
    url: '/project/records/add',
    method: 'post',
    data: data
  })
}
// 进修详情
export function meetingInfo(id) {
export function recordsInfo(id) {
  return request({
    url: '/project/meeting/getInfo/' + id,
    url: '/project/records/getInfo/' + id,
    method: 'get'
  })
}
// 删除
export function recordsDel(id) {
  return request({
    url: '/project/records/remove/' + id,
    method: 'get'
  })
}
// 导出捐献器官管理
export function exporrecords(query) {
  return request({
    url: '/project/records/export',
    method: 'get',
    params: query
  })
}
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">
          新建会议
@@ -37,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"
@@ -53,11 +52,22 @@
            clearable
            placeholder="请选择"
          >
            <el-option label="待开始" value="pending" />
            <el-option label="进行中" value="ongoing" />
            <el-option label="已结束" value="completed" />
            <el-option label="已取消" value="cancelled" />
            <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>
@@ -75,7 +85,7 @@
        style="width: 100%"
        @sort-change="handleSortChange"
      >
        <!-- <el-table-column prop="id" label="ID" width="80" fixed /> -->
        <el-table-column prop="id" label="ID" width="80" fixed align="center" />
        <el-table-column
          prop="title"
          align="center"
@@ -84,7 +94,7 @@
          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>
@@ -96,38 +106,32 @@
          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
          align="center"
          prop="status"
          label="状态"
          label="会议状态"
          width="100"
          fixed="right"
        >
          <template #default="scope">
            <el-tag :type="getStatusTag(scope.row.status)">
              {{ getStatusText(scope.row.status) }}
            <el-tag :type="getMeetingStatusTag(scope.row.status)">
              {{ getMeetingStatusText(scope.row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          prop="participants"
          label="参会人员"
          align="center"
          width="180"
          show-overflow-tooltip
        >
          <template #default="scope">
            <span>{{ scope.row.participants.join(", ") }}</span>
          </template>
        </el-table-column>
          prop="organizerName"
          label="组织者"
          width="120"
        />
        <el-table-column
          align="center"
          prop="location"
          prop="locationName"
          label="会议地点"
          width="150"
        />
@@ -176,25 +180,42 @@
              size="mini"
              type="text"
              @click="handleViewMinutes(scope.row)"
              :disabled="!scope.row.meetingMinutes"
              :disabled="!scope.row.recordcontent"
            >
              {{ scope.row.meetingMinutes ? "查看纪要" : "暂无" }}
              {{ 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="操作" 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>
@@ -203,6 +224,7 @@
              type="text"
              @click="handleDelete(scope.row)"
              style="color: #F56C6C;"
              :disabled="scope.row.delFlag === 1"
            >
              删除
            </el-button>
@@ -213,22 +235,24 @@
      <!-- 分页 -->
      <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.meetingMinutes">
      <div v-if="currentRecord.recordcontent">
        <el-alert
          title="会议纪要详情"
          type="info"
@@ -240,7 +264,7 @@
            <div
              style="white-space: pre-line; line-height: 1.6; max-height: 300px; overflow-y: auto;"
            >
              {{ currentRecord.meetingMinutes }}
              {{ currentRecord.recordcontent }}
            </div>
          </el-card>
        </div>
@@ -249,15 +273,15 @@
        <div
          class="minutes-attachments"
          v-if="
            currentRecord.minutesAttachments &&
              currentRecord.minutesAttachments.length > 0
            currentRecord.recordattachment &&
              parseAttachments(currentRecord.recordattachment).length > 0
          "
        >
          <el-divider content-position="left">会议纪要附件</el-divider>
          <div class="attachment-list">
            <div
              v-for="file in currentRecord.minutesAttachments"
              :key="file.id"
              v-for="file in parseAttachments(currentRecord.recordattachment)"
              :key="file.id || file.name"
              class="attachment-item"
            >
              <el-link
@@ -267,11 +291,13 @@
                class="file-link"
              >
                <i
                  :class="getFileIcon(file.type)"
                  :class="getFileIcon(file.type || file.name)"
                  style="margin-right: 8px;"
                ></i>
                {{ file.name }}
                <span class="file-size">({{ formatFileSize(file.size) }})</span>
                <span class="file-size" v-if="file.size"
                  >({{ formatFileSize(file.size) }})</span
                >
              </el-link>
            </div>
          </div>
@@ -282,11 +308,10 @@
          style="margin-top: 16px; color: #909399; font-size: 12px;"
        >
          <span
            >创建时间:
            {{ formatDateTime(currentRecord.minutesCreateTime) }}</span
            >记录时间: {{ formatDateTime(currentRecord.recorderTime) }}</span
          >
          <span style="margin-left: 16px;"
            >创建人: {{ currentRecord.minutesCreator || "系统" }}</span
            >记录人: {{ currentRecord.recorderBy || "未指定" }}</span
          >
        </div>
      </div>
@@ -297,13 +322,14 @@
        <el-button @click="minutesDialogVisible = false">关闭</el-button>
        <el-button
          type="primary"
          @click="handleEdit(currentRecord)"
          v-if="currentRecord.meetingMinutes"
          @click="handleEdit(currentRecord.id)"
          v-if="currentRecord.recordcontent"
        >
          编辑纪要
        </el-button>
      </span>
    </el-dialog>
    <!-- 查看详情对话框 -->
    <el-dialog
      :title="`会议详情 - ${currentRecord.title || ''}`"
@@ -311,34 +337,29 @@
      width="800px"
      :before-close="handleDetailClose"
    >
      <el-descriptions :column="2" border v-if="currentRecord">
      <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="组织者">{{
          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>
@@ -348,57 +369,62 @@
        <el-descriptions-item label="持续时间">{{
          calculateDuration(currentRecord)
        }}</el-descriptions-item>
        <el-descriptions-item label="创建人">{{
          currentRecord.creator
        <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
            v-html="currentRecord.content"
            style="white-space: pre-line; max-height: 300px; overflow-y: auto;"
          >
            {{ currentRecord.content }}
          </div>
          ></div>
        </el-descriptions-item>
        <el-descriptions-item label="会议详情附件" :span="2">
        <!-- 会议附件 -->
        <el-descriptions-item label="会议附件" :span="2">
          <div class="detail-attachments">
            <div
              v-if="
                currentRecord.detailAttachments &&
                  currentRecord.detailAttachments.length > 0
                currentRecord.attachment &&
                  parseAttachments(currentRecord.attachment).length > 0
              "
              class="attachment-grid"
            >
              <div
                v-for="file in currentRecord.detailAttachments"
                :key="file.id"
                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)" class="file-icon"></i>
                    <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">{{
                        <span class="file-size" v-if="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
                    >
                  <div class="file-actions" v-if="file.url">
                    <el-button
                      type="text"
                      size="mini"
@@ -410,61 +436,37 @@
              </div>
            </div>
            <div v-else class="no-attachment">
              <el-empty
                description="暂无会议详情附件"
                :image-size="50"
              ></el-empty>
              <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-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>
@@ -486,143 +488,33 @@
          <el-input v-model="editForm.title" placeholder="请输入会议主题" />
        </el-form-item>
        <el-form-item label="会议类型" prop="meetingType">
        <el-form-item label="会议类型" prop="typeId">
          <el-select
            v-model="editForm.meetingType"
            v-model="editForm.typeId"
            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-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="participants">
        <el-form-item label="会议地点" prop="locationId">
          <el-select
            v-model="editForm.participants"
            multiple
            filterable
            placeholder="请选择参会人员"
            v-model="editForm.locationId"
            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-select>
        </el-form-item>
        <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">
@@ -648,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"
@@ -664,20 +569,79 @@
            v-model="editForm.content"
            type="textarea"
            :rows="6"
            placeholder="请输入会议具体内容"
            placeholder="请输入会议具体内容(支持HTML格式)"
          />
        </el-form-item>
        <!-- 会议纪要附件上传 -->
        <el-form-item label="会议纪要附件">
        <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="handleMinutesFileChange"
              :file-list="editForm.minutesAttachments"
              :on-change="handleMinutesAttachmentChange"
              :file-list="editForm.recordattachmentFiles"
              :limit="5"
              multiple
            >
@@ -690,18 +654,14 @@
            </el-upload>
          </div>
        </el-form-item>
        <el-form-item label="会议纪要" prop="meetingMinutes">
        <el-form-item label="备注" prop="remark">
          <el-input
            v-model="editForm.meetingMinutes"
            v-model="editForm.remark"
            type="textarea"
            :rows="6"
            placeholder="请输入会议纪要内容,包括会议决议、行动计划、责任人等信息"
            maxlength="1000"
            show-word-limit
            :rows="2"
            placeholder="请输入备注信息"
          />
          <div style="color: #909399; font-size: 12px; margin-top: 4px;">
            提示:可记录会议讨论要点、决议事项、行动计划等
          </div>
        </el-form-item>
      </el-form>
@@ -716,12 +676,22 @@
</template>
<script>
import {
  meetinglist,
  meetingedit,
  meetingadd,
  meetingInfo,
  meetingDel,
  exporremeeting
} from "@/api/officeManagementApi";
export default {
  name: "MeetingManagement",
  data() {
    return {
      // 查询参数
      queryParams: {
        title: "",
        meetingType: "",
        location: "",
        dateRange: [],
@@ -729,7 +699,7 @@
      },
      // 分页参数
      pagination: {
        currentPage: 1,
        pageNum: 1,
        pageSize: 10,
        total: 0
      },
@@ -739,51 +709,23 @@
      // 对话框显示状态
      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: "吴十" }
      ],
      minutesDialogVisible: false, // 会议纪要对话框显示状态
      // 编辑表单数据
      editForm: {
        title: "",
        meetingType: "",
        participants: [],
        location: "",
        startTime: "",
        endTime: "",
        summary: "",
        content: "",
        attachments: [],
        detailAttachments: [], // 会议详情附件
        summaryAttachments: [], // 会议概要附件
        minutesAttachments: [] // 会议纪要附件
      },
      editForm: this.getDefaultFormData(),
      // 表单验证规则
      editRules: {
        title: [{ required: true, message: "请输入会议主题", trigger: "blur" }],
        meetingType: [
        typeId: [
          { required: true, message: "请选择会议类型", trigger: "change" }
        ],
        participants: [
          { required: true, message: "请选择参会人员", trigger: "change" }
        ],
        location: [
          { required: true, message: "请输入会议地点", trigger: "blur" }
        locationId: [
          { required: true, message: "请选择会议地点", trigger: "change" }
        ],
        startTime: [
          { required: true, message: "请选择开始时间", trigger: "change" }
@@ -797,12 +739,8 @@
        content: [
          { required: true, message: "请输入会议内容", trigger: "blur" }
        ],
        meetingMinutes: [
          {
            max: 1000,
            message: "会议纪要长度不能超过1000个字符",
            trigger: "blur"
          }
        reminderMinutes: [
          { required: true, message: "请输入提前提醒时间", trigger: "blur" }
        ]
      }
    };
@@ -815,12 +753,29 @@
    async loadData() {
      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("数据加载失败");
@@ -828,7 +783,14 @@
        this.loading = false;
      }
    },
    getFileIcon(fileType) {
    // 获取文件图标
    getFileIcon(fileName) {
      if (!fileName) return "el-icon-document";
      const ext = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const iconMap = {
        pdf: "el-icon-document",
        doc: "el-icon-document",
@@ -844,227 +806,99 @@
        zip: "el-icon-folder",
        rar: "el-icon-folder"
      };
      return iconMap[fileType] || "el-icon-document";
      return iconMap[ext] || "el-icon-document";
    },
    // 查看会议纪要
    handleViewMinutes(record) {
      this.currentRecord = { ...record };
      this.minutesDialogVisible = true;
    },
    // 生成模拟数据
    generateMockData() {
      const meetingTypes = [
        "research",
        "daily",
        "project",
        "department",
        "review"
      ];
      const statuses = ["pending", "ongoing", "completed", "cancelled"];
      const participantsPool = [
        "张三",
        "李四",
        "王五",
        "赵六",
        "钱七",
        "孙八",
        "周九",
        "吴十"
      ];
      // 会议纪要示例内容
      const minutesExamples = [
        `会议决议:
1. 项目计划调整至下周一正式启动
2. 技术方案由张三负责完善
3. 下周进行技术评审会议
行动计划:
- 李四:准备技术文档(截止周五)
- 王五:协调资源分配(截止周四)
- 全体:参加技术培训(周三下午)`,
        `讨论要点:
1. 当前项目进度正常,需加强质量管控
2. 客户反馈问题需要优先处理
3. 下阶段工作重点明确
任务分配:
✅ 已完成:需求分析、技术方案
🔷 进行中:开发实施(负责人:赵六)
⏳ 待开始:测试验收`,
        `重要决议:
• 通过预算调整方案
• 确定新成员加入时间
• 批准设备采购申请
后续安排:
📅 下次会议时间:2024-01-15 14:00
📍 会议地点:第一会议室
👥 必须参会人员:张三、李四`
      ];
      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]);
    // 解析附件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
        );
        // 随机决定是否有会议纪要(60%概率有纪要)
        const hasMinutes = Math.random() > 0.4;
        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: `关于${
            ["科研项目", "日常工作", "技术评审", "部门协调"][
              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,
          location: ["第一会议室", "第二会议室", "第三会议室", "线上会议"][
            Math.floor(Math.random() * 4)
          ],
          startTime: startTime.toISOString(),
          endTime: endTime.toISOString(),
          summary: `本次会议主要讨论${
            ["项目进展", "技术难题", "工作计划", "问题协调"][
              Math.floor(Math.random() * 4)
            ]
          }等相关事宜`,
          content: `会议详细内容:\n1. 议题一讨论\n2. 议题二分析\n3. 下一步工作计划\n4. 任务分配`,
          meetingMinutes: meetingMinutes,
          minutesCreateTime: hasMinutes
            ? new Date(startTime.getTime() + 3600000).toISOString()
            : "",
          minutesCreator: hasMinutes ? participants[0] : "",
          status: statuses[Math.floor(Math.random() * statuses.length)],
          creator: "系统管理员",
          attachments: []
        };
      });
        return attachmentJson;
      } catch (error) {
        console.error("解析附件失败:", error);
        return [];
      }
    },
    // 获取会议类型标签样式
    getMeetingTypeTag(type) {
    getMeetingTypeTag(typeId) {
      const typeMap = {
        research: "primary",
        daily: "success",
        project: "warning",
        department: "info",
        review: "danger"
        1: "primary", // 科研会议
        2: "success", // 日常会议
        3: "warning", // 项目会议
        4: "info", // 部门会议
        5: "danger" // 评审会议
      };
      return typeMap[type] || "info";
      return typeMap[typeId] || "info";
    },
    // 获取会议类型文本
    getMeetingTypeText(type) {
    getMeetingTypeText(typeId) {
      const textMap = {
        research: "科研会议",
        daily: "日常会议",
        project: "项目会议",
        department: "部门会议",
        review: "评审会议"
        1: "科研会议",
        2: "日常会议",
        3: "项目会议",
        4: "部门会议",
        5: "评审会议"
      };
      return textMap[type] || type;
      return textMap[typeId] || "其他";
    },
    // 获取状态标签样式
    getStatusTag(status) {
    // 获取会议状态标签样式
    getMeetingStatusTag(status) {
      const statusMap = {
        pending: "primary",
        ongoing: "success",
        completed: "info",
        cancelled: "danger"
        1: "primary", // 待开始
        2: "success", // 进行中
        3: "info", // 已结束
        4: "danger" // 已取消
      };
      return statusMap[status] || "info";
    },
    // 获取状态文本
    getStatusText(status) {
    // 获取会议状态文本
    getMeetingStatusText(status) {
      const textMap = {
        pending: "待开始",
        ongoing: "进行中",
        completed: "已结束",
        cancelled: "已取消"
        1: "待开始",
        2: "进行中",
        3: "已结束",
        4: "已取消"
      };
      return textMap[status] || status;
      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");
      return dateTime.replace("T", " ");
    },
    // 计算会议持续时间
@@ -1083,28 +917,48 @@
      }
    },
    // 格式化文件大小
    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.pagination.pageNum = 1;
      this.loadData();
    },
    // 重置查询
    handleReset() {
      this.queryParams = {
        title: "",
        meetingType: "",
        location: "",
        dateRange: [],
        status: ""
      };
      this.pagination.currentPage = 1;
      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("获取详情失败");
      }
    },
    // 新增记录
@@ -1118,114 +972,200 @@
    },
    // 编辑记录
    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 };
          // 解析附件
          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;
          // 解析附件
          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;
    async handleDelete(record) {
      try {
        await this.$confirm("确定要删除这条会议记录吗?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        });
        const response = await meetingDel(record.id);
        if (response.code === 200) {
          this.$message.success("删除成功");
        })
        .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];
          this.loadData();
        } else {
          this.$message.error(response.msg || "删除失败");
        }
      } catch (error) {
        if (error !== "cancel") {
          console.error("删除失败:", error);
          this.$message.error("删除失败");
        }
      }
    },
    // 分类型文件上传处理
    handleDetailFileChange(file, fileList) {
      this.editForm.detailAttachments = fileList;
    // 文件上传处理
    handleAttachmentChange(file, fileList) {
      this.editForm.attachmentFiles = fileList;
    },
    handleSummaryFileChange(file, fileList) {
      this.editForm.summaryAttachments = fileList;
    },
    handleMinutesFileChange(file, fileList) {
      this.editForm.minutesAttachments = fileList;
    handleMinutesAttachmentChange(file, fileList) {
      this.editForm.recordattachmentFiles = fileList;
    },
    // 删除已上传的文件
    handleRemoveDetailFile(index) {
      this.editForm.detailAttachments.splice(index, 1);
    handleRemoveAttachmentFile(index) {
      this.editForm.attachmentFiles.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}`);
      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;
        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("操作失败");
        this.$message.error(this.isEditing ? "保存失败" : "新增失败");
      } finally {
        this.saveLoading = false;
      }
    },
    // 文件上传处理
    handleFileChange(file, fileList) {
      this.editForm.attachments = fileList;
    },
    // 关闭详情对话框
@@ -1238,6 +1178,7 @@
    handleEditClose() {
      this.editDialogVisible = false;
      this.currentRecord = {};
      this.editForm = this.getDefaultFormData();
      this.$nextTick(() => {
        this.$refs.editForm && this.$refs.editForm.clearValidate();
      });
@@ -1245,19 +1186,28 @@
    // 导出数据
    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.pagination.pageNum = 1;
      this.loadData();
    },
    // 当前页变化
    handleCurrentChange(page) {
      this.pagination.currentPage = page;
      this.pagination.pageNum = page;
      this.loadData();
    },
@@ -1266,23 +1216,30 @@
      console.log("排序变化:", sort);
    },
    // 更新默认表单数据
    // 获取默认表单数据
    getDefaultFormData() {
      return {
        id: null,
        title: "",
        meetingType: "",
        participants: [],
        location: "",
        typeId: null,
        locationId: null,
        startTime: "",
        endTime: "",
        summary: "",
        content: "",
        meetingMinutes: "",
        minutesCreateTime: "",
        minutesCreator: "",
        detailAttachments: [],
        summaryAttachments: [],
        minutesAttachments: []
        attachment: null,
        attachmentFiles: [],
        status: 1, // 默认待开始
        isRecurring: 0,
        recurringPattern: null,
        parentMeetingId: null,
        reminderMinutes: 30,
        recordcontent: "",
        recordattachment: null,
        recordattachmentFiles: [],
        recorderBy: "",
        remark: "",
        approvalStatus: 0 // 默认待审核
      };
    }
  }
@@ -1326,13 +1283,6 @@
.minutes-meta {
  border-top: 1px solid #e4e7ed;
  padding-top: 12px;
}
/* 会议纪要文本区域样式 */
.minutes-textarea {
  font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
  font-size: 13px;
  line-height: 1.5;
}
/* 响应式调整 */
@@ -1419,7 +1369,7 @@
.file-icon {
  font-size: 24px;
  color: #409EFF;
  color: #409eff;
  margin-right: 10px;
}
src/views/OfficeRelated/engage/index.vue
@@ -2,7 +2,6 @@
  <div class="training-management">
    <!-- 页面头部 -->
    <div class="page-header">
      <h2>进修管理</h2>
      <div class="header-actions">
        <el-button type="primary" icon="el-icon-plus" @click="handleAdd">
          新增进修记录
@@ -69,15 +68,15 @@
        <el-table-column prop="id" label="ID" width="80" fixed />
        <el-table-column prop="name" label="姓名" width="100" fixed>
          <template #default="scope">
            <el-button type="text" @click="handleView(scope.row)">
            <el-button type="text" @click="handleView(scope.row.id)">
              {{ scope.row.name }}
            </el-button>
          </template>
        </el-table-column>
        <el-table-column prop="gender" label="性别" width="80">
        <el-table-column prop="sex" label="性别" width="80">
          <template #default="scope">
            <el-tag :type="scope.row.gender === '男' ? 'primary' : 'danger'" size="small">
              {{ scope.row.gender }}
            <el-tag :type="scope.row.sex === '男' ? 'primary' : 'danger'" size="small">
              {{ scope.row.sex }}
            </el-tag>
          </template>
        </el-table-column>
@@ -90,38 +89,54 @@
            </el-tag>
          </template>
        </el-table-column>
                <el-table-column prop="trainingStartDate" label="进修开始时间" width="120" />
        <el-table-column prop="trainingEndDate" label="进修结束时间" width="120" />
        <el-table-column prop="trainingStartDate" label="进修开始时间" width="120">
          <template #default="scope">
            {{ formatDate(scope.row.trainingStartDate) }}
          </template>
        </el-table-column>
        <el-table-column prop="trainingEndDate" label="进修结束时间" width="120">
          <template #default="scope">
            {{ formatDate(scope.row.trainingEndDate) }}
          </template>
        </el-table-column>
        <el-table-column prop="trainingMajor" label="进修专业" width="120" />
        <el-table-column prop="idCard" label="身份证号" width="180" show-overflow-tooltip />
        <el-table-column prop="technicalTitle" label="技术职称" width="120" />
        <el-table-column prop="professionalField" label="从事专业" width="120" />
        <el-table-column prop="profession" label="从事专业" width="120" />
        <el-table-column prop="workYears" label="工作年限" width="100" sortable />
        <el-table-column prop="graduateSchool" label="毕业院校" width="150" show-overflow-tooltip />
        <el-table-column prop="graduationSchool" label="毕业院校" width="150" show-overflow-tooltip />
        <el-table-column prop="workUnit" label="所在单位" width="150" show-overflow-tooltip />
        <el-table-column prop="status" label="状态" width="100" fixed="right">
        <el-table-column prop="recordStatus" label="状态" width="100" fixed="right">
          <template #default="scope">
            <el-tag :type="getStatusTag(scope.row.status)">
              {{ scope.row.status }}
            <el-tag :type="getStatusTag(scope.row.recordStatus)">
              {{ scope.row.recordStatus || '进行中' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180" 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)">
              编辑
            </el-button>
            <el-button
              size="mini"
              type="text"
              @click="handleCopy(scope.row)"
              @click="handleCopy(scope.row.id)"
              style="color: #67C23A;"
            >
              复制
            </el-button>
            <el-button
              size="mini"
              type="text"
              @click="handleDelete(scope.row)"
              style="color: #F56C6C;"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
@@ -130,10 +145,11 @@
      <!-- 分页 -->
      <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"
        />
@@ -147,9 +163,9 @@
      width="900px"
      :before-close="handleDetailClose"
    >
      <el-descriptions :column="2" border v-if="currentRecord">
      <el-descriptions :column="2" border v-if="currentRecord.id">
        <el-descriptions-item label="姓名">{{ currentRecord.name }}</el-descriptions-item>
        <el-descriptions-item label="性别">{{ currentRecord.gender }}</el-descriptions-item>
        <el-descriptions-item label="性别">{{ currentRecord.sex }}</el-descriptions-item>
        <el-descriptions-item label="年龄">{{ currentRecord.age }}</el-descriptions-item>
        <el-descriptions-item label="学历">{{ currentRecord.education }}</el-descriptions-item>
        <el-descriptions-item label="进修类型">
@@ -158,31 +174,37 @@
          </el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="身份证号">{{ currentRecord.idCard }}</el-descriptions-item>
        <el-descriptions-item label="毕业院校">{{ currentRecord.graduateSchool }}</el-descriptions-item>
        <el-descriptions-item label="毕业院校">{{ currentRecord.graduationSchool }}</el-descriptions-item>
        <el-descriptions-item label="所在单位">{{ currentRecord.workUnit }}</el-descriptions-item>
        <el-descriptions-item label="技术职称">{{ currentRecord.technicalTitle }}</el-descriptions-item>
        <el-descriptions-item label="从事专业">{{ currentRecord.professionalField }}</el-descriptions-item>
        <el-descriptions-item label="从事专业">{{ currentRecord.profession }}</el-descriptions-item>
        <el-descriptions-item label="工作年限">{{ currentRecord.workYears }}年</el-descriptions-item>
        <el-descriptions-item label="进修目标">{{ currentRecord.trainingObjective }}</el-descriptions-item>
        <el-descriptions-item label="进修开始时间">{{ currentRecord.trainingStartDate }}</el-descriptions-item>
        <el-descriptions-item label="进修结束时间">{{ currentRecord.trainingEndDate }}</el-descriptions-item>
        <el-descriptions-item label="进修目标">{{ currentRecord.trainingGoal }}</el-descriptions-item>
        <el-descriptions-item label="进修开始时间">{{ formatDate(currentRecord.trainingStartDate) }}</el-descriptions-item>
        <el-descriptions-item label="进修结束时间">{{ formatDate(currentRecord.trainingEndDate) }}</el-descriptions-item>
        <el-descriptions-item label="进修专业">{{ currentRecord.trainingMajor }}</el-descriptions-item>
        <el-descriptions-item label="从事工作情况" :span="2">
          {{ currentRecord.workSituation }}
        </el-descriptions-item>
        <el-descriptions-item label="进修科目及目的" :span="2">
          {{ currentRecord.trainingSubject }}
        <el-descriptions-item label="进修科目" :span="2">
          {{ currentRecord.applySubject }}
        </el-descriptions-item>
        <el-descriptions-item label="进修目的" :span="2">
          {{ currentRecord.applyPurpose }}
        </el-descriptions-item>
        <el-descriptions-item label="主要学历" :span="2">
          <div style="white-space: pre-line;">{{ currentRecord.mainEducation }}</div>
        </el-descriptions-item>
        <el-descriptions-item label="主要工作经历" :span="2">
          <div style="white-space: pre-line;">{{ currentRecord.workExperience }}</div>
          <div style="white-space: pre-line;">{{ currentRecord.mainExperience }}</div>
        </el-descriptions-item>
        <el-descriptions-item label="创建时间">{{ formatDateTime(currentRecord.createTime) }}</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)">编辑</el-button>
      </span>
    </el-dialog>
@@ -207,8 +229,8 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="性别" prop="gender">
              <el-radio-group v-model="editForm.gender">
            <el-form-item label="性别" prop="sex">
              <el-radio-group v-model="editForm.sex">
                <el-radio label="男">男</el-radio>
                <el-radio label="女">女</el-radio>
              </el-radio-group>
@@ -255,8 +277,8 @@
          <el-input v-model="editForm.idCard" placeholder="请输入身份证号" />
        </el-form-item>
        <el-form-item label="毕业院校" prop="graduateSchool">
          <el-input v-model="editForm.graduateSchool" placeholder="请输入毕业院校" />
        <el-form-item label="毕业院校" prop="graduationSchool">
          <el-input v-model="editForm.graduationSchool" placeholder="请输入毕业院校" />
        </el-form-item>
        <el-form-item label="所在单位" prop="workUnit">
@@ -270,8 +292,8 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="从事专业" prop="professionalField">
              <el-input v-model="editForm.professionalField" placeholder="请输入从事专业" />
            <el-form-item label="从事专业" prop="profession">
              <el-input v-model="editForm.profession" placeholder="请输入从事专业" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -281,14 +303,16 @@
            v-model="editForm.workYears"
            :min="0"
            :max="50"
            :precision="1"
            :step="0.5"
            controls-position="right"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item label="进修目标" prop="trainingObjective">
        <el-form-item label="进修目标" prop="trainingGoal">
          <el-input
            v-model="editForm.trainingObjective"
            v-model="editForm.trainingGoal"
            type="textarea"
            :rows="2"
            placeholder="请输入进修目标"
@@ -302,7 +326,7 @@
                v-model="editForm.trainingStartDate"
                type="date"
                placeholder="选择开始日期"
                value-format="yyyy-MM-dd"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
              />
            </el-form-item>
@@ -313,7 +337,7 @@
                v-model="editForm.trainingEndDate"
                type="date"
                placeholder="选择结束日期"
                value-format="yyyy-MM-dd"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
              />
            </el-form-item>
@@ -324,21 +348,30 @@
          <el-input v-model="editForm.trainingMajor" placeholder="请输入进修专业" />
        </el-form-item>
        <el-form-item label="进修科目" prop="applySubject">
          <el-input
            v-model="editForm.applySubject"
            type="textarea"
            :rows="2"
            placeholder="请输入本次申请进修科目"
          />
        </el-form-item>
        <el-form-item label="进修目的" prop="applyPurpose">
          <el-input
            v-model="editForm.applyPurpose"
            type="textarea"
            :rows="2"
            placeholder="请输入进修目的要求"
          />
        </el-form-item>
        <el-form-item label="从事工作情况" prop="workSituation">
          <el-input
            v-model="editForm.workSituation"
            type="textarea"
            :rows="3"
            placeholder="请输入从事工作情况"
          />
        </el-form-item>
        <el-form-item label="进修科目及目的" prop="trainingSubject">
          <el-input
            v-model="editForm.trainingSubject"
            type="textarea"
            :rows="3"
            placeholder="请输入本次申请进修何种科目及目的要求"
          />
        </el-form-item>
@@ -351,14 +384,23 @@
          />
        </el-form-item>
        <el-form-item label="主要工作经历" prop="workExperience">
        <el-form-item label="主要工作经历" prop="mainExperience">
          <el-input
            v-model="editForm.workExperience"
            v-model="editForm.mainExperience"
            type="textarea"
            :rows="3"
            placeholder="请输入主要工作经历(每行一条)"
          />
        </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">
@@ -372,6 +414,8 @@
</template>
<script>
import { recordslist, recordsedit, recordsadd, recordsInfo, recordsDel,exporrecords } from "@/api/officeManagementApi";
export default {
  name: 'TrainingManagement',
  data() {
@@ -385,7 +429,7 @@
      },
      // 分页参数
      pagination: {
        currentPage: 1,
        pageNum: 1,
        pageSize: 10,
        total: 0
      },
@@ -402,35 +446,20 @@
      // 表格数据
      tableData: [],
      // 编辑表单数据
      editForm: {
        name: '',
        gender: '男',
        age: 25,
        education: '',
        trainingType: '',
        idCard: '',
        graduateSchool: '',
        workUnit: '',
        technicalTitle: '',
        professionalField: '',
        workYears: 0,
        trainingObjective: '',
        trainingStartDate: '',
        trainingEndDate: '',
        trainingMajor: '',
        workSituation: '',
        trainingSubject: '',
        mainEducation: '',
        workExperience: ''
      },
      editForm: this.getDefaultFormData(),
      // 表单验证规则
      editRules: {
        name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
        gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
        sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
        age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],
        education: [{ required: true, message: '请选择学历', trigger: 'change' }],
        trainingType: [{ required: true, message: '请选择进修类型', trigger: 'change' }],
        idCard: [{ required: true, message: '请输入身份证号', trigger: 'blur' }]
        idCard: [
          { required: true, message: '请输入身份证号', trigger: 'blur' },
          { pattern: /^\d{17}[\dXx]$/, message: '请输入正确的身份证号', trigger: 'blur' }
        ],
        trainingStartDate: [{ required: true, message: '请选择进修开始时间', trigger: 'change' }],
        trainingEndDate: [{ required: true, message: '请选择进修结束时间', trigger: 'change' }]
      }
    }
  },
@@ -442,12 +471,26 @@
    async loadData() {
      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.startDate = this.queryParams.dateRange[0]
          params.endDate = this.queryParams.dateRange[1]
        }
        const response = await recordslist(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('数据加载失败')
@@ -455,36 +498,7 @@
        this.loading = false
      }
    },
    // 生成模拟数据
    generateMockData() {
      const names = ['张三', '李四', '王五', '赵六', '钱七', '孙八', '周九', '吴十']
      const trainingTypes = ['professional', 'management', 'education', 'skill']
      const statuses = ['进行中', '已完成', '待审核', '已取消']
      return Array.from({ length: 10 }, (_, index) => ({
        id: index + 1,
        name: names[Math.floor(Math.random() * names.length)],
        gender: Math.random() > 0.5 ? '男' : '女',
        age: 25 + Math.floor(Math.random() * 20),
        education: ['博士', '硕士', '本科', '大专'][Math.floor(Math.random() * 4)],
        trainingType: trainingTypes[Math.floor(Math.random() * trainingTypes.length)],
        idCard: '11010119900101' + (1000 + index).toString().slice(-4),
        graduateSchool: ['北京大学', '清华大学', '复旦大学', '上海交通大学'][Math.floor(Math.random() * 4)],
        workUnit: ['青岛大学附属医院', '青岛市市立医院', '山东大学齐鲁医院', '青岛市中心医院'][Math.floor(Math.random() * 4)],
        technicalTitle: ['主任医师', '副主任医师', '主治医师', '住院医师'][Math.floor(Math.random() * 4)],
        professionalField: ['心血管内科', '神经外科', '儿科', '妇产科'][Math.floor(Math.random() * 4)],
        workYears: 5 + Math.floor(Math.random() * 20),
        trainingObjective: '提升专业技术和临床能力',
        trainingStartDate: '2024-' + (Math.floor(Math.random() * 12) + 1).toString().padStart(2, '0') + '-01',
        trainingEndDate: '2024-' + (Math.floor(Math.random() * 12) + 1).toString().padStart(2, '0') + '-28',
        trainingMajor: '临床医学',
        workSituation: '在临床一线工作,负责患者诊疗',
        trainingSubject: '高级心血管介入治疗技术',
        mainEducation: '2005-2009 大学医学部 临床医学本科\n2009-2012 大学医学部 硕士',
        workExperience: '2012-2015 协和医院 住院医师\n2015-2020 协和医院 主治医师',
        status: statuses[Math.floor(Math.random() * statuses.length)]
      }))
    },
    // 获取进修类型标签样式
    getTrainingTypeTag(type) {
      const typeMap = {
@@ -495,6 +509,7 @@
      }
      return typeMap[type] || 'info'
    },
    // 获取进修类型文本
    getTrainingTypeText(type) {
      const textMap = {
@@ -505,21 +520,38 @@
      }
      return textMap[type] || type
    },
    // 获取状态标签样式
    getStatusTag(status) {
      const statusMap = {
        '进行中': 'primary',
        '已完成': 'success',
        '待审核': 'warning',
        '已取消': 'danger'
        '已取消': 'danger',
        '正常': 'success',
        '删除': 'danger'
      }
      return statusMap[status] || 'info'
    },
    // 格式化日期
    formatDate(date) {
      if (!date) return ''
      return date.split(' ')[0]
    },
    // 格式化日期时间
    formatDateTime(dateTime) {
      if (!dateTime) return ''
      return dateTime.replace('T', ' ')
    },
    // 查询处理
    handleQuery() {
      this.pagination.currentPage = 1
      this.pagination.pageNum = 1
      this.loadData()
    },
    // 重置查询
    handleReset() {
      this.queryParams = {
@@ -528,14 +560,26 @@
        technicalTitle: '',
        dateRange: []
      }
      this.pagination.currentPage = 1
      this.pagination.pageNum = 1
      this.loadData()
    },
    // 查看详情
    handleView(record) {
      this.currentRecord = { ...record }
      this.detailDialogVisible = true
    async handleView(id) {
      try {
        const response = await recordsInfo(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
@@ -545,29 +589,54 @@
        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 recordsInfo(id)
        if (response.code === 200) {
          this.isEditing = true
          this.currentRecord = response.data || {}
          this.editForm = { ...response.data }
          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.name = copiedRecord.name + '(复制)'
      this.editForm = copiedRecord
      this.editDialogVisible = true
      this.$nextTick(() => {
        this.$refs.editForm && this.$refs.editForm.clearValidate()
      })
    async handleCopy(id) {
      try {
        const response = await recordsInfo(id)
        if (response.code === 200) {
          this.isEditing = false
          const copiedRecord = { ...response.data }
          delete copiedRecord.id
          copiedRecord.name = copiedRecord.name + '(复制)'
          copiedRecord.isCopy = 1
          copiedRecord.originalId = id
          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('获取记录失败')
      }
    },
    // 保存记录
    async handleSave() {
      try {
@@ -575,74 +644,140 @@
        if (!valid) return
        this.saveLoading = true
        // 模拟API调用
        await new Promise(resolve => setTimeout(resolve, 1000))
        this.$message.success(this.isEditing ? '保存成功' : '新增成功')
        this.editDialogVisible = false
        this.loadData()
        // 验证结束时间不能早于开始时间
        if (this.editForm.trainingStartDate && this.editForm.trainingEndDate) {
          if (this.editForm.trainingEndDate < this.editForm.trainingStartDate) {
            this.$message.error('结束时间不能早于开始时间')
            this.saveLoading = false
            return
          }
        }
        let response
        if (this.isEditing) {
          // 编辑
          response = await recordsedit(this.editForm)
        } else {
          // 新增
          response = await recordsadd(this.editForm)
        }
        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('操作失败')
        this.$message.error(this.isEditing ? '保存失败' : '新增失败')
      } finally {
        this.saveLoading = false
      }
    },
    // 删除记录
    async handleDelete(row) {
      try {
        await this.$confirm('确定要删除这条记录吗?', '提示', {
          type: 'warning',
          confirmButtonText: '确定',
          cancelButtonText: '取消'
        })
        const response = await recordsDel(row.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('删除失败')
        }
      }
    },
    // 关闭详情对话框
    handleDetailClose() {
      this.detailDialogVisible = false
      this.currentRecord = {}
    },
    // 关闭编辑对话框
    handleEditClose() {
      this.editDialogVisible = false
      this.currentRecord = {}
      this.editForm = this.getDefaultFormData()
      this.$nextTick(() => {
        this.$refs.editForm && this.$refs.editForm.clearValidate()
      })
    },
    // 导出数据
    exportData() {
      this.$message.success('导出功能开发中')
       const queryParams = this.queryParams;
      this.$modal
        .confirm("是否确认导出所有进修管理数据项?")
        .then(() => {
          return exporrecords(queryParams);
        })
        .then((response) => {
          this.$download.name(response.msg);
        })
        .catch(() => { });
    },
    // 分页大小变化
    handleSizeChange(size) {
      this.pagination.pageSize = size
      this.pagination.currentPage = 1
      this.pagination.pageNum = 1
      this.loadData()
    },
    // 当前页变化
    handleCurrentChange(page) {
      this.pagination.currentPage = page
      this.pagination.pageNum = page
      this.loadData()
    },
    // 排序变化
    handleSortChange(sort) {
      console.log('排序变化:', sort)
      // 这里可以添加排序逻辑
      // 这里可以添加排序逻辑,如果需要的话
    },
    // 获取默认表单数据
    getDefaultFormData() {
      return {
        id: null,
        name: '',
        gender: '男',
        sex: '男',
        age: 25,
        education: '',
        trainingType: '',
        idCard: '',
        graduateSchool: '',
        graduationSchool: '',
        workUnit: '',
        technicalTitle: '',
        professionalField: '',
        profession: '',
        workYears: 0,
        trainingObjective: '',
        trainingGoal: '',
        trainingStartDate: '',
        trainingEndDate: '',
        trainingMajor: '',
        workSituation: '',
        trainingSubject: '',
        applySubject: '',
        applyPurpose: '',
        mainEducation: '',
        workExperience: ''
        mainExperience: '',
        remark: '',
        isCopy: 0,
        originalId: null
      }
    }
  }
src/views/business/affirm/affirmInfo.vue
@@ -341,7 +341,7 @@
</template>
<script>
import { relativesList, relativesEdit } from "@/api/businessApi";
import { relativesList, relativesEdit, relativesAdd } from "@/api/businessApi";
import FilePreviewDialog from "@/components/FilePreviewDialog";
export default {
@@ -511,8 +511,7 @@
          ? detailData.organdecision
          : detailData.organdecision.split(",");
      }
      console.log(this.organdecision,'this.organdecision');
      console.log(this.organdecision, "this.organdecision");
      // 处理附件数据 - 从assessannex字段解析JSON并按类型分类
      this.processAssessannexData();
@@ -806,8 +805,12 @@
          organdecisionOther: this.organdecisionOther
          // assessannex字段已在updateAssessannexField中更新
        };
        const response = await relativesEdit(saveData);
        let response = null;
        if (saveData.id) {
          response = await relativesEdit(saveData);
        } else {
          response = await relativesAdd(saveData);
        }
        if (response.code === 200) {
          this.$message.success("保存成功");
src/views/business/affirm/index.vue
@@ -358,15 +358,15 @@
        if (Array.isArray(response.data)) {
          // 如果返回的是数组
          this.confirmationList = response.data;
          this.total = response.data.length;
          this.total = response.total;
        } else if (response.data.rows) {
          // 如果返回的是分页数据结构
          this.confirmationList = response.data.rows;
          this.total = response.data.total;
          this.total = response.total;
        } else if (Array.isArray(response.data.list)) {
          // 如果返回的是list字段
          this.confirmationList = response.data.list;
          this.total = response.data.total || response.data.list.length;
          this.total = response.total;
        } else {
          // 其他数据结构,尝试直接使用data
          this.confirmationList = response.data;