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