- Maven 模块从 ruoyi-ccdi 重命名为 ruoyi-info-collection - Java 包名从 com.ruoyi.ccdi 改为 com.ruoyi.info.collection - MyBatis XML 命名空间同步更新 - 保留数据库表名、API URL、权限标识中的 ccdi 前缀 - 更新项目文档中的模块引用
210 lines
6.3 KiB
Markdown
210 lines
6.3 KiB
Markdown
# 采购交易导入功能问题修复总结
|
||
|
||
## 修复日期
|
||
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` (导入测试脚本)
|