10 KiB
10 KiB
出国申请附件下载问题分析与修复方案
🔍 问题描述
现象:
- ✅ ID 37 的申请可以正常下载盖章附件
- ❌ ID 39 的申请点击下载提示"文件OSS ID不存在"
- 新增申请上传的附件都无法下载
📊 问题根因分析
1. 数据库对比
请在数据库中执行以下SQL查询:
-- 查询ID 37和ID 39的关键字段对比
SELECT
application_id AS '申请ID',
applicant_name AS '申请人',
stamped_registration_file_name AS '盖章文件名',
stamped_file_oss_id AS '盖章OSS_ID',
DATE_FORMAT(stamped_file_upload_time, '%Y-%m-%d %H:%i:%s') AS '上传时间',
CASE
WHEN stamped_file_oss_id IS NOT NULL THEN '✅ 正常'
ELSE '❌ 缺失OSS_ID'
END AS '状态'
FROM rs_overseas_application
WHERE application_id IN (37, 38, 39) AND deleted = 0
ORDER BY application_id;
预期结果:
| 申请ID | 盖章文件名 | 盖章OSS_ID | 状态 |
|---|---|---|---|
| 37 | xxx.pdf | 197xxxxxxxxx | ✅ 正常 |
| 38 | xxx.pdf | NULL | ❌ 缺失OSS_ID |
| 39 | xxx.pdf | NULL | ❌ 缺失OSS_ID |
2. 根本原因
问题代码位置:web/src/views/rs/overseas/index.vue 第727行
<el-upload
:action="uploadStampedFileAction"
:data="{ applicationId: applicationForm.applicationId || 0 }"
...
>
问题分析:
- 用户点击"新增申请"→
applicationForm是空对象,applicationId为undefined - 用户上传盖章文件 → 传递
applicationId=0给后端 - 后端
updateStampedFileInfo方法无法找到applicationId=0的记录 - OSS文件虽然上传成功,但
stamped_file_oss_id字段未更新 - 点击下载时检查OSS_ID为NULL,提示"文件OSS ID不存在"
为什么ID 37可以下载?
ID 37可能是通过以下方式创建的:
- 先点击"新增"并填写表单
- 点击"确定"保存申请(此时获得了applicationId)
- 再次点击"编辑"
- 上传盖章文件(此时applicationId已经存在)
✅ 修复方案
方案1:修改前端上传逻辑(推荐)
思路
在用户上传文件前,先自动保存申请记录(草稿状态),获得applicationId,然后再上传文件。
具体步骤
步骤1:修改后端add接口,返回新创建的ID
文件:backend/ruoyi-modules/ruoyi-rs/src/main/java/org/dromara/rs/controller/RsOverseasApplicationController.java
找到第184行的add方法,修改返回类型:
// 修改前
@PostMapping
public R<Void> add(@Validated(AddGroup.class) @RequestBody RsOverseasApplicationBo bo) {
// ... 现有逻辑 ...
return toAjax(applicationService.insertByBo(bo));
}
// 修改后
@PostMapping
public R<Map<String, Object>> add(@Validated(AddGroup.class) @RequestBody RsOverseasApplicationBo bo) {
// ... 现有逻辑 ...
boolean result = applicationService.insertByBo(bo);
if (result) {
// 返回新创建的applicationId
Map<String, Object> data = new HashMap<>();
data.put("applicationId", bo.getApplicationId());
return R.ok("操作成功", data);
} else {
return R.fail("新增失败");
}
}
步骤2:修改前端上传前的钩子函数
文件:web/src/views/rs/overseas/index.vue
找到beforeStampedFileUpload方法(约2220行),修改如下:
// 上传前的验证
const beforeStampedFileUpload = async (file: File) => {
// 检查文件格式
const validTypes = ['application/pdf', 'image/jpeg', 'image/jpg', 'image/png'];
if (!validTypes.includes(file.type)) {
ElMessage.error('只支持PDF、JPG、PNG格式的文件');
return false;
}
// 检查文件大小(10MB)
const maxSize = 10 * 1024 * 1024;
if (file.size > maxSize) {
ElMessage.error('文件大小不能超过10MB');
return false;
}
// 🔴 关键修复:如果是新增模式(没有applicationId),先保存申请记录
if (!state.applicationForm.applicationId) {
try {
ElMessage.info('正在保存申请记录...');
// 执行必要的字段映射
if (state.applicationForm.startDate) {
state.applicationForm.startDate = dayjs(state.applicationForm.startDate).format('YYYY-MM-DD');
}
if (state.applicationForm.endDate) {
state.applicationForm.endDate = dayjs(state.applicationForm.endDate).format('YYYY-MM-DD');
}
if (state.applicationForm.birthDate) {
state.applicationForm.birthDate = dayjs(state.applicationForm.birthDate).format('YYYY-MM-DD');
}
// 保存申请记录(草稿状态)
const response = await addOverseasApplication(state.applicationForm);
// 🔴 重要:从响应中获取新创建的applicationId
if (response.data && response.data.applicationId) {
state.applicationForm.applicationId = response.data.applicationId;
ElMessage.success('申请记录已保存,现在可以上传盖章文件了');
} else {
ElMessage.error('保存申请记录失败,无法获取申请ID');
return false;
}
return true;
} catch (error) {
console.error('保存申请记录失败:', error);
ElMessage.error('保存申请记录失败,请先手动保存');
return false;
}
}
return true;
};
步骤3:(可选)使用computed动态获取applicationId
如果上面的修改不生效,可以将:data改为计算属性:
找到第727行,修改如下:
<!-- 修改前 -->
:data="{ applicationId: applicationForm.applicationId || 0 }"
<!-- 修改后 -->
:data="uploadStampedFileData"
然后在script中添加计算属性(约1430行附近):
// 上传盖章文件的data参数
const uploadStampedFileData = computed(() => {
return {
applicationId: state.applicationForm.applicationId || 0
};
});
方案2:临时修复数据库(快速解决ID 39的问题)
步骤1:查找ID 39对应的OSS文件
-- 查询sys_oss表中ID 39上传的文件
SELECT
oss_id,
file_name,
original_name,
url,
DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') AS create_time
FROM sys_oss
WHERE DATE(create_time) = CURDATE() -- 今天上传的
AND original_name LIKE '%pdf%' -- PDF文件
ORDER BY create_time DESC
LIMIT 10;
步骤2:手动更新rs_overseas_application表
找到ID 39对应的oss_id后,执行:
-- 假设找到的oss_id是 1976886772986052610
UPDATE rs_overseas_application
SET stamped_file_oss_id = 1976886772986052610
WHERE application_id = 39 AND deleted = 0;
-- 验证更新
SELECT
application_id,
stamped_file_oss_id,
stamped_registration_file_name
FROM rs_overseas_application
WHERE application_id = 39 AND deleted = 0;
步骤3:刷新前端页面测试
Cmd + Shift + R (macOS)
Ctrl + F5 (Windows)
🧪 测试步骤
1. 测试新增申请流程
-
进入出国申请管理
-
点击"新增"按钮
-
填写必填字段:
- 政治面貌:选择任意值
- 出国开始日期:2025-11-01
- 出国结束日期:2025-11-10
- 紧急联系人:张三 13800138000
- 目的国家:美国
-
上传盖章文件(不要先点击确定):
- 选择一个PDF文件
- 观察是否出现"正在保存申请记录..."提示
- 观察是否上传成功
-
点击"确定"提交申请
-
进入"我的申请",找到刚才新增的记录
-
点击"查看详情"
-
点击下载盖章文件
- ✅ 预期:文件可以正常下载
- ❌ 如果失败:查看控制台错误信息
2. 验证数据库
-- 查询最新的申请记录
SELECT
application_id,
applicant_name,
stamped_registration_file_name,
stamped_file_oss_id,
CASE
WHEN stamped_file_oss_id IS NOT NULL THEN '✅ 正常'
ELSE '❌ 异常'
END AS status
FROM rs_overseas_application
WHERE deleted = 0
ORDER BY application_id DESC
LIMIT 5;
预期:新增的记录中stamped_file_oss_id字段不为NULL。
📋 修复检查清单
后端修改
- 修改
RsOverseasApplicationController.add方法返回类型 - 返回
applicationId字段 - 重启后端服务
前端修改
- 修改
beforeStampedFileUpload方法 - 添加自动保存申请记录的逻辑
- (可选)添加
uploadStampedFileData计算属性 - 刷新前端页面(Cmd+Shift+R)
数据库修复
- 查询ID 39对应的OSS文件ID
- 更新
rs_overseas_application表的stamped_file_oss_id字段 - 验证更新结果
功能测试
- 测试新增申请并上传附件
- 验证可以正常下载
- 检查数据库OSS_ID字段是否正常保存
💡 为什么这样修复?
问题本质
El-upload组件的auto-upload模式下,文件选择后立即上传,此时表单可能还未保存,applicationId不存在。
解决思路
- 在上传前拦截:使用
before-upload钩子 - 自动保存表单:如果没有ID,先调用新增接口
- 获取真实ID:从响应中提取
applicationId - 继续上传:使用真实ID作为参数
技术要点
before-upload钩子可以返回Promise<boolean>,用于异步验证- 新增接口需要返回
applicationId供后续使用 - 使用
computed包装:data,确保响应式更新
🔧 如果修复后仍然失败
调试步骤
-
检查后端日志
IDEA控制台查看是否有错误信息 -
检查前端Console
// 在beforeStampedFileUpload方法中添加 console.log('当前applicationId:', state.applicationForm.applicationId); -
检查Network请求
F12 → Network → 找到uploadStampedFile请求 查看Payload中的applicationId是否为0 -
检查数据库
-- 查看最新记录 SELECT * FROM rs_overseas_application WHERE deleted = 0 ORDER BY application_id DESC LIMIT 1;
📞 需要帮助?
如果按照以上步骤修复后仍然有问题,请提供:
- 后端控制台的完整日志
- 前端Console的错误信息
- Network面板的uploadStampedFile请求详情
- 数据库查询结果截图
创建时间:2025-10-11
问题优先级:🔴 高
预计修复时间:30分钟
建议修复顺序:
- 先执行方案2(临时修复数据库),立即解决ID 39的问题
- 再执行方案1(修改代码),解决根本问题
- 最后进行完整测试