Files
hzdyjs/出国申请附件显示修复说明.md
T
2025-10-14 16:41:19 +08:00

12 KiB
Raw Blame History

出国申请附件显示修复说明

问题描述

用户通过"出国申请"菜单新增申请时,上传了以下两个附件:

  1. 出国境登记表盖章文件
  2. 党籍保留附件

但在点击"查看详情"按钮时,弹窗中未显示这两个附件。


问题原因分析

根本原因

后端VO类缺少党籍保留附件相关字段

数据库表字段(完整)

rs_overseas_application 表中包含以下字段:

  • stamped_registration_file_path - 登记备案表盖章文件路径
  • stamped_registration_file_name - 登记备案表盖章文件名
  • stamped_file_upload_time - 盖章文件上传时间
  • stamped_file_upload_status - 盖章文件上传状态
  • stamped_file_oss_id - 盖章文件OSS ID
  • party_retention_file_path - 党籍保留附件文件路径
  • party_retention_file_name - 党籍保留附件文件名
  • party_retention_upload_time - 党籍保留附件上传时间
  • party_retention_upload_status - 党籍保留附件上传状态
  • party_retention_file_oss_id - 党籍保留附件OSS ID

后端实体类(RsOverseasApplication.java)- ✅ 完整

private String partyRetentionFilePath;
private String partyRetentionFileName;
private Date partyRetentionUploadTime;
private String partyRetentionUploadStatus;
private Long partyRetentionFileOssId;

后端VO类(RsOverseasApplicationVo.java)- ❌ 缺失

修复前:只有 partyRetentionFileOssId,缺少以下字段:

  • partyRetentionFilePath
  • partyRetentionFileName
  • partyRetentionUploadTime
  • partyRetentionUploadStatus

导致问题:

  • 前端调用查看详情API时,后端返回的VO数据中没有党籍保留附件的文件名、上传时间等信息
  • 前端无法判断是否有党籍保留附件上传(partyRetentionUploadStatus 为空)
  • 前端详情弹窗的条件渲染失效:v-if="partyRetentionUploadStatus === '1'" 始终为false

修复方案

1️⃣ 后端修复:补充VO字段

文件:backend/ruoyi-modules/ruoyi-rs/src/main/java/org/dromara/rs/domain/vo/RsOverseasApplicationVo.java

修改位置:第332-356行

修改内容:在 stampedFileOssId 之后补充党籍保留附件的完整字段

/**
 * 党籍保留附件文件路径
 */
private String partyRetentionFilePath;

/**
 * 党籍保留附件文件名
 */
private String partyRetentionFileName;

/**
 * 党籍保留附件上传时间
 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date partyRetentionUploadTime;

/**
 * 党籍保留附件上传状态:0-未上传,1-已上传
 */
private String partyRetentionUploadStatus;

/**
 * 党籍保留附件OSS ID(用于安全下载)
 */
private Long partyRetentionFileOssId;

2️⃣ 前端修复:补充TypeScript接口字段

文件:web/src/api/rs/overseas.ts

修改位置:第55-64行(OverseasApplicationVO接口)

修改内容:补充党籍保留附件和OSS ID字段

export interface OverseasApplicationVO {
  // ... 其他字段 ...
  stampedFileOssId?: number; // 盖章文件OSS ID
  partyRetentionFilePath?: string; // 党籍保留附件文件路径
  partyRetentionFileName?: string; // 党籍保留附件文件名
  partyRetentionUploadTime?: string; // 党籍保留附件上传时间
  partyRetentionUploadStatus?: string; // 党籍保留附件上传状态
  partyRetentionFileOssId?: number; // 党籍保留附件OSS ID
  // ... 其他字段 ...
}

前端详情弹窗显示逻辑

文件:web/src/views/rs/overseas/index.vue

出国境登记表盖章文件显示(第997-1022行)

<div v-if="(state.viewData as OverseasApplicationVO).stampedFileUploadStatus === '1'" 
     style="margin-bottom: 15px; padding: 12px; border: 1px solid #e4e7ed; border-radius: 4px; background: #f9fafb;">
  <div style="font-size: 14px; color: #606266; margin-bottom: 8px;">
    <el-icon><Document /></el-icon>
    <span style="margin-left: 5px; font-weight: 500;">出国境登记表盖章文件</span>
  </div>
  <div style="display: flex; align-items: center; justify-content: space-between;">
    <div style="flex: 1;">
      <el-tag type="success" size="small">
        <el-icon><Document /></el-icon>
        {{ (state.viewData as OverseasApplicationVO).stampedRegistrationFileName }}
      </el-tag>
      <span style="margin-left: 10px; font-size: 12px; color: #909399;">
        上传时间: {{ (state.viewData as OverseasApplicationVO).stampedFileUploadTime }}
      </span>
    </div>
    <el-button link type="primary" size="small" @click="handleDownloadStampedFile">
      <el-icon><Download /></el-icon> 下载
    </el-button>
  </div>
</div>

条件渲染:

  • v-if="stampedFileUploadStatus === '1'" - 只有上传状态为"1"(已上传)时才显示
  • 显示文件名:stampedRegistrationFileName
  • 显示上传时间:stampedFileUploadTime

党籍保留附件显示(第1024-1050行)

<div v-if="(state.viewData as OverseasApplicationVO).partyRetentionUploadStatus === '1'" 
     style="margin-bottom: 15px; padding: 12px; border: 1px solid #e4e7ed; border-radius: 4px; background: #fff5f5;">
  <div style="font-size: 14px; color: #ff4757; margin-bottom: 8px;">
    <el-icon><Warning /></el-icon>
    <span style="margin-left: 5px; font-weight: 500;">党籍保留附件</span>
  </div>
  <div style="display: flex; align-items: center; justify-content: space-between;">
    <div style="flex: 1;">
      <el-tag type="danger" size="small">
        <el-icon><Document /></el-icon>
        {{ (state.viewData as OverseasApplicationVO).partyRetentionFileName }}
      </el-tag>
      <span style="margin-left: 10px; font-size: 12px; color: #909399;">
        上传时间: {{ (state.viewData as OverseasApplicationVO).partyRetentionUploadTime }}
      </span>
    </div>
    <el-button link type="primary" size="small" @click="handleDownloadPartyRetentionFile">
      <el-icon><Download /></el-icon> 下载
    </el-button>
  </div>
</div>

条件渲染:

  • v-if="partyRetentionUploadStatus === '1'" - 只有上传状态为"1"(已上传)时才显示
  • 显示文件名:partyRetentionFileName(✅ 修复后可用)
  • 显示上传时间:partyRetentionUploadTime(✅ 修复后可用)

修复效果

修复前 ❌

  • 问题1:党籍保留附件区域不显示(条件渲染失败)
  • 原因:partyRetentionUploadStatus 字段为空/undefined

修复后 ✅

  • 出国境登记表盖章文件:
    • 显示文件名、上传时间
    • 提供下载按钮
  • 党籍保留附件:
    • 显示文件名、上传时间(✅ 字段补全后可用)
    • 提供下载按钮

部署步骤

1️⃣ 后端部署

Step 1: 编译代码(已完成)

cd /Users/weizzzz/Documents/Cursor/0828CURSOR/all-project/backend
mvn clean compile -DskipTests -pl ruoyi-modules/ruoyi-rs -am

编译结果:✅ BUILD SUCCESS

Step 2: 重启后端服务

方法1:IDEA重启

  1. 停止当前运行的 RuoYi-Admin 服务
  2. 重新运行 RuoYi-Admin 启动类

方法2:命令行重启

# 停止现有进程
ps aux | grep ruoyi-admin
kill -9 <pid>

# 启动服务
cd ruoyi-admin
mvn spring-boot:run

2️⃣ 前端部署

前端无需重新编译

  • TypeScript 接口更新后,前端代码无需重新编译
  • 浏览器刷新即可生效

浏览器刷新

硬刷新(清除缓存):

  • Windows: Ctrl + Shift + R
  • Mac: Cmd + Shift + R

验证步骤

1️⃣ 准备测试数据

新增出国申请(包含附件)

  1. 点击"出国申请"菜单
  2. 点击"新增申请"按钮
  3. 填写表单信息
  4. 上传"出国境登记表盖章文件"
  5. 上传"党籍保留附件"(如果是党员)
  6. 点击"提交"按钮

2️⃣ 验证详情弹窗显示

查看详情

  1. 在出国申请列表中找到刚才新增的申请
  2. 点击"查看详情"按钮
  3. 验证点:
    • ✅ 出国境登记表盖章文件区域显示
    • ✅ 显示文件名(如:出国登记表-盖章.pdf)
    • ✅ 显示上传时间(如:2025-10-11 10:30:15)
    • ✅ 党籍保留附件区域显示(如果是党员且已上传)
    • ✅ 显示文件名(如:党籍保留材料.pdf)
    • ✅ 显示上传时间(如:2025-10-11 10:31:20)

3️⃣ 验证下载功能

下载附件

  1. 点击"出国境登记表盖章文件"的"下载"按钮
    • ✅ 文件开始下载
    • ✅ 文件名正确
  2. 点击"党籍保留附件"的"下载"按钮
    • ✅ 文件开始下载
    • ✅ 文件名正确

技术要点

AutoMapper 自动映射

注解:@AutoMapper(target = RsOverseasApplication.class)

作用:

  • 自动将 RsOverseasApplication 实体类的字段映射到 RsOverseasApplicationVo
  • 字段名相同的会自动映射
  • 要求:VO类必须包含对应的字段,否则不会映射

为什么需要手动补充字段:

  • 虽然有 @AutoMapper 注解
  • 但VO类中必须显式声明所有需要返回的字段
  • 缺失的字段不会自动添加,需要手动补充

JSON序列化

时间字段格式化:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date partyRetentionUploadTime;

作用:

  • 将 Date 类型转换为指定格式的字符串
  • 前端接收到的数据:"2025-10-11 10:31:20" 而不是时间戳

参考

对比:培训申请附件显示实现

文件:web/src/views/rs/training/index.vue

相似功能:

  • 培训申请详情弹窗中也显示附件列表
  • 实现方式:通过 attachmentIds 字段查询附件列表
  • 显示逻辑:使用 el-table 展示附件列表

出国申请的差异:

  • 出国申请有两类特殊附件(盖章文件、党籍附件)
  • 直接将附件信息存储在主表中(而不是关联附件表)
  • 使用条件渲染显示(v-if)而不是表格列表

总结

修复内容

  1. ✅ 后端VO补充字段:添加党籍保留附件的4个字段
  2. ✅ 前端TS接口补充字段:添加党籍保留附件和OSS ID字段
  3. ✅ 后端编译成功:无错误

待验证

  1. ⏳ 重启后端服务:应用VO字段更改
  2. ⏳ 前端刷新验证:硬刷新浏览器
  3. ⏳ 功能验证:查看详情弹窗显示附件
  4. ⏳ 下载验证:附件下载功能正常

修复时间

修复日期:2025-10-11
修复内容:出国申请查看详情弹窗附件不显示问题


附录:字段对照表

字段用途 数据库字段 实体类字段 VO类字段 前端TS接口
盖章文件路径 stamped_registration_file_path stampedRegistrationFilePath stampedRegistrationFilePath stampedRegistrationFilePath
盖章文件名 stamped_registration_file_name stampedRegistrationFileName stampedRegistrationFileName stampedRegistrationFileName
盖章上传时间 stamped_file_upload_time stampedFileUploadTime stampedFileUploadTime stampedFileUploadTime
盖章上传状态 stamped_file_upload_status stampedFileUploadStatus stampedFileUploadStatus stampedFileUploadStatus
盖章文件OSS ID stamped_file_oss_id stampedFileOssId stampedFileOssId stampedFileOssId
党籍附件路径 party_retention_file_path partyRetentionFilePath ✅ partyRetentionFilePath ✅ partyRetentionFilePath
党籍附件文件名 party_retention_file_name partyRetentionFileName ✅ partyRetentionFileName ✅ partyRetentionFileName
党籍上传时间 party_retention_upload_time partyRetentionUploadTime ✅ partyRetentionUploadTime ✅ partyRetentionUploadTime
党籍上传状态 party_retention_upload_status partyRetentionUploadStatus ✅ partyRetentionUploadStatus ✅ partyRetentionUploadStatus
党籍文件OSS ID party_retention_file_oss_id partyRetentionFileOssId partyRetentionFileOssId ✅ partyRetentionFileOssId

✅ = 本次修复补充的字段


修复完成!请重启后端服务并刷新前端验证功能。