Files
ccdi/doc/requirements/plans/2026-02-08-purchase-transaction-import-fixes.md
wkc 1cd87d2695 refactor: 重命名 ruoyi-ccdi 模块为 ruoyi-info-collection
- Maven 模块从 ruoyi-ccdi 重命名为 ruoyi-info-collection
- Java 包名从 com.ruoyi.ccdi 改为 com.ruoyi.info.collection
- MyBatis XML 命名空间同步更新
- 保留数据库表名、API URL、权限标识中的 ccdi 前缀
- 更新项目文档中的模块引用
2026-02-24 17:12:11 +08:00

210 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 采购交易导入功能问题修复总结
## 修复日期
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-info-collection/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiPurchaseTransactionExcel.java:52-82`
**修改内容**:
```java
// 修改前
private String purchaseQty;
private String budgetAmount;
private String bidAmount;
// ... 其他金额字段
// 修改后
private BigDecimal purchaseQty;
private BigDecimal budgetAmount;
private BigDecimal bidAmount;
// ... 其他金额字段
```
---
### 问题2: 查看失败记录弹窗显示"暂无数据"
**现象**:
- 导入失败后,点击"查看导入失败记录"按钮
- 后端接口返回了失败记录数据
- 前端页面显示"暂无数据"
**根本原因**:
- 前端期望接口返回分页格式:`{rows: [...], total: N}`
- 后端接口返回的是简单列表:`{data: [...]}`
- 后端接口缺少分页参数和分页逻辑
**修复方案**:
参照员工信息管理模块,修改采购交易管理的查询失败记录接口:
1. 添加分页参数pageNum、pageSize
2. 实现手动分页逻辑
3. 返回类型从 `AjaxResult` 改为 `TableDataInfo`
4. 使用 `getDataTable()` 方法返回分页格式
**修改文件**:
- `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/controller/CcdiPurchaseTransactionController.java:173-196`
**修改内容**:
```java
// 修改前
@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. 正常导入场景(数据完整)
1. 上传Excel文件
2. 后端异步处理,验证数据
3. 所有数据通过验证,成功插入数据库
4. 前端收到完成通知:`导入完成!全部成功!共导入2000条数据`
5. 列表刷新,显示新导入的数据
### 2. 部分失败场景(数据有误)
1. 上传Excel文件
2. 后端异步处理,验证数据
3. 部分数据验证失败失败记录保存到Redis
4. 前端收到完成通知:`导入完成!成功1800条,失败200条`
5. 操作栏显示"查看导入失败记录"按钮
6. 点击按钮,打开失败记录对话框
7. 对话框显示分页的失败记录列表:
- 采购事项ID
- 项目名称
- 标的物名称
- 失败原因
8. 支持分页查询每页10条
9. 支持清除历史记录
---
## 测试建议
### 1. 测试正常导入
- 使用修复后的测试数据:`purchase_test_data_2000_fixed.xlsx`
- 预期结果全部成功2000条记录导入成功
### 2. 测试失败记录查看
- 使用有问题的测试数据(故意制造错误数据)
- 预期结果:
- 显示部分成功通知
- 显示"查看导入失败记录"按钮
- 点击后能看到失败记录列表
- 分页功能正常
### 3. 测试状态持久化
- 导入有失败的数据
- 刷新页面
- 预期结果:"查看导入失败记录"按钮仍然显示
---
## 修复验证清单
- [x] 修改Excel实体类字段类型
- [x] 重新编译后端成功
- [x] 修改查询失败记录接口
- [x] 添加分页支持
- [x] 重新编译后端成功
- [ ] 重启后端服务
- [ ] 测试正常导入
- [ ] 测试失败记录查看
- [ ] 验证前端显示正常
---
## 下一步操作
**需要手动执行**
1. 重启后端服务(加载新编译的代码)
2. 使用修复后的测试数据进行导入测试
3. 验证失败记录查看功能正常
---
## 技术说明
### Excel数值字段处理
- **EasyExcel** 会根据Java字段类型自动转换
- String类型 → 读取为字符串(空值可能为空字符串)
- BigDecimal类型 → 读取为数值空值为null
- BeanUtils.copyProperties() 会自动处理类型转换
### 分页数据格式
```javascript
// 前端期望的格式
{
"code": 200,
"msg": "查询成功",
"rows": [...], // 当前页数据
"total": 100 // 总记录数
}
```
### 若依框架分页方法
```java
// 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;
}
```
---
## 附录:相关文件
### 修改的文件
1. `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/excel/CcdiPurchaseTransactionExcel.java`
2. `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/controller/CcdiPurchaseTransactionController.java`
### 参考文件
1. `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/controller/CcdiEmployeeController.java` (员工信息管理,作为参考)
### 测试文件
1. `doc/test-data/purchase_transaction/generate-test-data.js` (测试数据生成脚本)
2. `doc/test-data/purchase_transaction/purchase_test_data_2000_fixed.xlsx` (修复后的测试数据)
3. `doc/test-data/purchase_transaction/test-import-debug.js` (导入测试脚本)