问题: - 导入成功条数显示为负数 - 原因:成功数量计算使用 validRecords.size() - failures.size() - 但没有使用实际的数据库操作返回值 修复: - saveBatchWithUpsert 和 saveBatch 方法现在返回 int - 累加实际的数据库影响行数 - 使用 actualSuccessCount 变量跟踪真实成功数量 影响范围: - CcdiIntermediaryPersonImportServiceImpl - CcdiIntermediaryEntityImportServiceImpl
6.3 KiB
6.3 KiB
采购交易导入功能问题修复总结
修复日期
2026-02-08
问题描述
问题1: 导入全部失败,提示"采购数量不能为空"
现象:
- 使用
purchase_test_data_2000.xlsx导入,2000条记录全部失败 - 错误信息:
采购数量不能为空 - 查询失败记录接口返回2000条记录
根本原因:
- Excel实体类
CcdiPurchaseTransactionExcel中,数值字段(purchaseQty、budgetAmount等)类型为 String - AddDTO
CcdiPurchaseTransactionAddDTO中,对应字段类型为 BigDecimal BeanUtils.copyProperties()进行 String → BigDecimal 转换时,空字符串转换为null- 测试数据中这些列为空,导致验证失败
修复方案:
修改 CcdiPurchaseTransactionExcel.java,将数值字段类型从 String 改为 BigDecimal
修改文件:
ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiPurchaseTransactionExcel.java:52-82
修改内容:
// 修改前
private String purchaseQty;
private String budgetAmount;
private String bidAmount;
// ... 其他金额字段
// 修改后
private BigDecimal purchaseQty;
private BigDecimal budgetAmount;
private BigDecimal bidAmount;
// ... 其他金额字段
问题2: 查看失败记录弹窗显示"暂无数据"
现象:
- 导入失败后,点击"查看导入失败记录"按钮
- 后端接口返回了失败记录数据
- 前端页面显示"暂无数据"
根本原因:
- 前端期望接口返回分页格式:
{rows: [...], total: N} - 后端接口返回的是简单列表:
{data: [...]} - 后端接口缺少分页参数和分页逻辑
修复方案: 参照员工信息管理模块,修改采购交易管理的查询失败记录接口:
- 添加分页参数(pageNum、pageSize)
- 实现手动分页逻辑
- 返回类型从
AjaxResult改为TableDataInfo - 使用
getDataTable()方法返回分页格式
修改文件:
ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiPurchaseTransactionController.java:173-196
修改内容:
// 修改前
@GetMapping("/importFailures/{taskId}")
public AjaxResult getImportFailures(@PathVariable String taskId) {
List<PurchaseTransactionImportFailureVO> failures = transactionImportService.getImportFailures(taskId);
return success(failures); // 返回 {data: [...]}
}
// 修改后
@GetMapping("/importFailures/{taskId}")
public TableDataInfo getImportFailures(
@PathVariable String taskId,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
List<PurchaseTransactionImportFailureVO> failures = transactionImportService.getImportFailures(taskId);
// 手动分页
int fromIndex = (pageNum - 1) * pageSize;
int toIndex = Math.min(fromIndex + pageSize, failures.size());
List<PurchaseTransactionImportFailureVO> pageData = failures.subList(fromIndex, toIndex);
return getDataTable(pageData, failures.size()); // 返回 {rows: [...], total: N}
}
修复后的完整流程
1. 正常导入场景(数据完整)
- 上传Excel文件
- 后端异步处理,验证数据
- 所有数据通过验证,成功插入数据库
- 前端收到完成通知:
导入完成!全部成功!共导入2000条数据 - 列表刷新,显示新导入的数据
2. 部分失败场景(数据有误)
- 上传Excel文件
- 后端异步处理,验证数据
- 部分数据验证失败,失败记录保存到Redis
- 前端收到完成通知:
导入完成!成功1800条,失败200条 - 操作栏显示"查看导入失败记录"按钮
- 点击按钮,打开失败记录对话框
- 对话框显示分页的失败记录列表:
- 采购事项ID
- 项目名称
- 标的物名称
- 失败原因
- 支持分页查询(每页10条)
- 支持清除历史记录
测试建议
1. 测试正常导入
- 使用修复后的测试数据:
purchase_test_data_2000_fixed.xlsx - 预期结果:全部成功,2000条记录导入成功
2. 测试失败记录查看
- 使用有问题的测试数据(故意制造错误数据)
- 预期结果:
- 显示部分成功通知
- 显示"查看导入失败记录"按钮
- 点击后能看到失败记录列表
- 分页功能正常
3. 测试状态持久化
- 导入有失败的数据
- 刷新页面
- 预期结果:"查看导入失败记录"按钮仍然显示
修复验证清单
- 修改Excel实体类字段类型
- 重新编译后端成功
- 修改查询失败记录接口
- 添加分页支持
- 重新编译后端成功
- 重启后端服务
- 测试正常导入
- 测试失败记录查看
- 验证前端显示正常
下一步操作
需要手动执行:
- 重启后端服务(加载新编译的代码)
- 使用修复后的测试数据进行导入测试
- 验证失败记录查看功能正常
技术说明
Excel数值字段处理
- EasyExcel 会根据Java字段类型自动转换
- String类型 → 读取为字符串(空值可能为空字符串)
- BigDecimal类型 → 读取为数值(空值为null)
- BeanUtils.copyProperties() 会自动处理类型转换
分页数据格式
// 前端期望的格式
{
"code": 200,
"msg": "查询成功",
"rows": [...], // 当前页数据
"total": 100 // 总记录数
}
若依框架分页方法
// BaseController.getDataTable() 方法
protected TableDataInfo getDataTable(List<?> list, long total) {
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(200);
rspData.setMsg("查询成功");
rspData.setRows(list);
rspData.setTotal(total);
return rspData;
}
附录:相关文件
修改的文件
ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiPurchaseTransactionExcel.javaruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiPurchaseTransactionController.java
参考文件
ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/controller/CcdiEmployeeController.java(员工信息管理,作为参考)
测试文件
doc/test-data/purchase_transaction/generate-test-data.js(测试数据生成脚本)doc/test-data/purchase_transaction/purchase_test_data_2000_fixed.xlsx(修复后的测试数据)doc/test-data/purchase_transaction/test-import-debug.js(导入测试脚本)