4.7 KiB
4.7 KiB
项目申报提交"申请人ID不能为空"问题修复记录
日期: 2025-08-01
操作人员: Assistant
修复类型: 后端数据验证和完整性修复
🚨 问题描述
用户在新增项目预算申报后点击提交时,提示失败,报错信息为"申请人ID不能为空"。
错误现象
- 操作: 新增项目预算申报 → 点击提交
- 结果: 提交失败
- 错误信息: "申请人ID不能为空"
🔍 问题分析
根本原因
- 数据库记录不完整: 已保存的项目申报记录中
applicant_id字段为NULL - 验证约束:
CwProjectApplicationBo中有严格的验证注解@NotNull(message = "申请人ID不能为空") - 历史数据问题: 可能存在早期创建但申请人信息不完整的记录
技术分析
// CwProjectApplicationBo.java 第210行
@NotNull(message = "申请人ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long applicantId;
🔧 修复方案
1. 后端代码修复
修改文件: backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/impl/CwProjectApplicationServiceImpl.java
修复内容: 在submitApplication方法中添加申请人信息检查和自动修复逻辑
// 检查并修复申请人信息
if (application.getApplicantId() == null) {
log.warn("项目申报记录申请人ID为空,正在修复:applicationId={}", id);
application.setApplicantId(LoginHelper.getUserId());
application.setApplicantName(LoginHelper.getUsername());
// 如果当前用户信息也获取不到,抛出明确错误
if (application.getApplicantId() == null) {
throw new RuntimeException("无法获取当前登录用户信息,请重新登录后重试");
}
}
// 检查部门信息
if (application.getDepartmentId() == null) {
log.warn("项目申报记录部门ID为空,正在修复:applicationId={}", id);
application.setDepartmentId(LoginHelper.getDeptId());
application.setDepartmentName(LoginHelper.getDeptName());
}
2. 数据库修复脚本
脚本文件: script/sql/fix-applicant-id-issue.sql
修复策略:
- 检查问题记录: 查找
applicant_id为NULL或0的记录 - 方案1: 将申请人ID设置为创建者ID(推荐)
- 方案2: 如果创建者也为空,设置为系统管理员
- 修复部门信息: 根据申请人ID补全部门信息
- 验证结果: 检查修复效果
3. 预防措施
-
新增记录时强制设置申请人信息:
// 在insertByBo方法中已有此逻辑 if (add.getApplicantId() == null) { add.setApplicantId(LoginHelper.getUserId()); } -
提交时二次检查: 在提交时再次验证和修复申请人信息
📋 修复步骤
步骤1: 执行数据库修复脚本
# 在数据库中执行
mysql -u username -p database_name < script/sql/fix-applicant-id-issue.sql
步骤2: 重启后端服务
cd backend
./start-main.sh
步骤3: 测试验证
- 登录系统
- 新增项目申报
- 点击提交,验证是否成功
- 检查后端日志,确认无错误
✅ 验证结果
预期效果
- ✅ 新增项目申报提交成功
- ✅ 申请人信息自动填充
- ✅ 审批流程正常创建
- ✅ 历史数据问题得到修复
验证SQL
-- 检查是否还有申请人ID为空的记录
SELECT COUNT(*) as problem_count
FROM cw_project_application
WHERE applicant_id IS NULL OR applicant_id = 0;
🔄 相关影响
正面影响
- 解决了项目申报提交失败的问题
- 修复了历史数据的完整性问题
- 提高了系统的稳定性和用户体验
- 增加了数据验证的容错性
注意事项
- 修复过程中会自动设置申请人信息
- 历史记录的申请人可能会变更为创建者
- 需要确保当前用户登录状态有效
📝 技术总结
问题根源
- 数据完整性约束: Bean Validation严格验证申请人ID
- 历史数据缺失: 早期记录可能缺少申请人信息
- 用户会话问题: 登录状态异常导致用户信息获取失败
解决策略
- 防御性编程: 在关键节点添加数据完整性检查
- 自动修复机制: 尝试从当前登录用户或创建者获取申请人信息
- 明确错误提示: 当无法修复时给出清晰的用户指导
最佳实践
- 数据验证前置: 在业务操作前进行必要的数据完整性检查
- 容错处理: 对于可以自动修复的数据问题,提供自动修复机制
- 日志记录: 记录数据修复过程,便于问题追踪和分析
这次修复不仅解决了当前问题,还建立了一套数据完整性保障机制。