guoyu/Test/备份/_已清理文件备份_周六 22512/md/导入进度显示优化说明.md

9.9 KiB
Raw Blame History

导入进度显示优化说明

问题现象

  1. 导入100条数据进度不显示或显示很慢
  2. 中断导入时显示"没有导入任何成功或失败的数据"
  3. 看不到正在做什么

🔍 问题原因

原因1进度更新频率太低

int updateInterval = 100;  // 每100条更新一次

问题:

  • 100条数据只更新2次进度第100条和结束时
  • 前99条处理时用户看不到任何进度
  • 导致用户以为系统卡死

原因2中断时结果保存不正确

// 只设置了progress.setResult()
// 但没有调用progressManager的方法保存
progress.setResult(resultMsg.toString());
return;  // 直接return结果丢失

原因3缺少详细的处理日志

// 只有进度日志
logger.info("任务 {} 进度更新: {}/{}", taskId, i, totalSize);

// 缺少:
// - 正在处理哪条记录
// - 新增还是更新
// - 处理结果如何

解决方案

优化1提高进度更新频率

修改前:

int updateInterval = 100;  // 每100条更新一次

修改后:

int updateInterval = 5;  // 每5条更新一次

效果:

  • 100条数据会更新20次进度
  • 用户每处理5条就能看到进度变化
  • 实时反馈,体验更好

优化2修复中断时的结果保存

修改前:

com.ddnai.common.core.domain.ImportProgress progress = progressManager.getProgress(taskId);
if (progress != null) {
    progress.setResult(resultMsg.toString());
}
return;  // 结果可能丢失

修改后:

// 使用progressManager的方法保存结果
progressManager.cancelTask(taskId, resultMsg.toString());
return;

效果:

  • 中断时正确保存已处理的结果
  • 显示新增、更新、失败的具体数量
  • 显示失败的详细信息

优化3添加详细的处理日志

新增用户时:

logger.info("正在新增用户: 信息编号={}, 姓名={}", infoNo, prisonerName);
userMapper.insertUser(user);
logger.info("用户新增成功: 信息编号={}, userId={}", infoNo, user.getUserId());

更新用户时:

logger.info("正在更新用户: 信息编号={}, 姓名={}", infoNo, prisonerName);
userMapper.updateUser(u);
logger.info("用户更新成功: 信息编号={}", infoNo);

进度更新时:

String progressInfo = String.format("[%d/%d] 新增:%d 更新:%d 失败:%d 跳过:%d", 
    i + 1, totalSize, successNum, updateNum, errorNum, duplicateNum);
logger.info("任务 {} 进度: {}", taskId, progressInfo);

📊 优化效果对比

优化前

项目 表现
进度更新 100条只更新2次
进度显示 99条时看不到进度
中断显示 "没有导入任何数据"
日志详细度 只有简单进度

优化后

项目 表现
进度更新 100条更新20次
进度显示 每5条就能看到
中断显示 显示已处理的详情
日志详细度 每条记录都有日志

📋 修改内容

文件: StudyClassUserServiceImpl.java

修改1进度更新频率第905行

// 每处理5条更新一次进度让用户看到实时进度
int updateInterval = 5;

修改2中断时保存结果第936行

// 保存取消状态和结果
progressManager.cancelTask(taskId, resultMsg.toString());

修改3新增详细日志第998-1000行

logger.info("正在新增用户: 信息编号={}, 姓名={}", infoNo, prisonerName);
userMapper.insertUser(user);
logger.info("用户新增成功: 信息编号={}, userId={}", infoNo, user.getUserId());

修改4更新详细日志第1092-1094行

logger.info("正在更新用户: 信息编号={}, 姓名={}", infoNo, prisonerName);
userMapper.updateUser(u);
logger.info("用户更新成功: 信息编号={}", infoNo);

修改5进度日志格式第1235-1237行

String progressInfo = String.format("[%d/%d] 新增:%d 更新:%d 失败:%d 跳过:%d", 
    i + 1, totalSize, successNum, updateNum, errorNum, duplicateNum);
logger.info("任务 {} 进度: {}", taskId, progressInfo);

🔧 部署步骤

步骤1重新编译

cd C:\Users\Administrator\Desktop\Project\ry_study-v_03\Study-Vue-redis
mvn clean package -DskipTests

步骤2重启服务

停止旧服务,启动新服务

步骤3测试导入

  1. 导入50条数据
  2. 观察进度是否实时更新
  3. 测试中断功能
  4. 查看日志详细程度

🧪 测试场景

场景1正常导入

操作:

  1. 导入100条数据
  2. 观察进度条

预期:

  • 进度条从0%逐步增加到100%
  • 每5条更新一次约每秒更新几次
  • 最终显示成功数量

日志示例:

正在新增用户: 信息编号=201, 姓名=张三
用户新增成功: 信息编号=201, userId=1001
任务 xxx 进度: [5/100] 新增:5 更新:0 失败:0 跳过:0
正在新增用户: 信息编号=206, 姓名=李四
用户新增成功: 信息编号=206, userId=1006
任务 xxx 进度: [10/100] 新增:10 更新:0 失败:0 跳过:0
...

场景2中断导入

操作:

  1. 开始导入100条数据
  2. 处理到第30条时点击"中断导入"

预期:

  • 显示中断提示
  • 显示已处理30条的详情
    导入已取消!
    新增: 20 条
    更新: 8 条
    失败: 2 条
    无变化跳过: 0 条
    未处理: 70 条
    
    失败详情:
    1、信息编号 205罪犯姓名 王五 导入失败:班级 [三班] 不存在
    2、信息编号 210罪犯姓名 赵六 导入失败:监区不能为空
    

场景3包含错误的导入

操作:

  1. 导入100条数据其中20条班级不存在

预期:

  • 进度实时更新
  • 最终显示:
    导入完成新增70条更新10条失败20条。
    
    失败详情:
    1、信息编号 205罪犯姓名 张三 导入失败:班级 [三班] 不存在
    ...逐条列出20条失败记录
    

日志示例:

正在新增用户: 信息编号=205, 姓名=张三
用户新增成功: 信息编号=205, userId=1005
为学员 205 分配班级时失败: 班级 [三班] 不存在,请先创建该班级
任务 xxx 进度: [5/100] 新增:4 更新:0 失败:1 跳过:0

📊 日志输出示例

完整的导入过程日志

[INFO] 任务 cce42e41-f819-4029-9c4e-0155fb3c2582 开始,共 100 条数据
[INFO] 预加载班级映射完成,共 5 个班级

[INFO] 正在新增用户: 信息编号=201, 姓名=张三
[INFO] 用户新增成功: 信息编号=201, userId=1001
[INFO] 为学员 201 分配班级 中级班1班 成功

[INFO] 正在新增用户: 信息编号=202, 姓名=李四
[INFO] 用户新增成功: 信息编号=202, userId=1002
[INFO] 为学员 202 分配班级 初级班1班 成功

[INFO] 正在新增用户: 信息编号=203, 姓名=王五
[INFO] 用户新增成功: 信息编号=203, userId=1003
[WARN] 为学员 203 分配班级时失败: 班级 [三班] 不存在,请先创建该班级

[INFO] 正在新增用户: 信息编号=204, 姓名=赵六
[INFO] 用户新增成功: 信息编号=204, userId=1004
[INFO] 为学员 204 分配班级 高级班1班 成功

[INFO] 正在新增用户: 信息编号=205, 姓名=孙七
[INFO] 用户新增成功: 信息编号=205, userId=1005
[INFO] 为学员 205 分配班级 攻坚转换班1班 成功

[INFO] 任务 xxx 进度: [5/100] 新增:5 更新:0 失败:0 跳过:0

[INFO] 正在更新用户: 信息编号=210, 姓名=周八
[INFO] 用户更新成功: 信息编号=210
[INFO] 为学员 210 更新班级为 中级班1班 成功

... (继续处理)

[INFO] 任务 xxx 进度: [10/100] 新增:8 更新:2 失败:0 跳过:0
[INFO] 任务 xxx 进度: [15/100] 新增:12 更新:3 失败:0 跳过:0
...
[INFO] 任务 xxx 进度: [100/100] 新增:70 更新:20 失败:5 跳过:5

[INFO] 任务 xxx 完成,最终结果:成功 70 条,更新 20 条,重复 5 条,失败 5 条

💡 进一步优化建议

1. 添加进度百分比

int percent = (i + 1) * 100 / totalSize;
logger.info("任务 {} 进度: {}% [{}]", taskId, percent, progressInfo);

2. 添加预计剩余时间

long elapsed = System.currentTimeMillis() - startTime;
long avgTime = elapsed / (i + 1);
long remaining = avgTime * (totalSize - i - 1);
logger.info("预计剩余时间: {} 秒", remaining / 1000);

3. 添加每秒处理速度

double speed = (i + 1) / (elapsed / 1000.0);
logger.info("处理速度: {:.1f} 条/秒", speed);

⚠️ 注意事项

1. 日志量增加

  • 每条记录产生2-3条日志
  • 100条数据约200-300条日志
  • 建议定期清理日志文件

2. 性能影响

  • 日志输出有一定性能开销
  • 但相比数据库操作可忽略
  • 如果追求极致性能可以只在DEBUG级别输出详细日志

3. 进度更新频率

  • 当前设置为每5条更新一次
  • 可根据实际情况调整3-10条都可以
  • 太频繁会增加网络开销

📋 验收标准

  • 导入100条数据进度实时更新每5条更新
  • 进度条流畅增长,无卡顿
  • 中断导入时显示已处理的详细信息
  • 日志显示每条记录的处理过程
  • 日志包含:正在处理、处理成功、失败原因
  • 最终结果统计正确

总结

核心改进

  1. 进度更新频率从100条提高到5条
  2. 中断时正确保存和显示结果
  3. 添加详细的处理日志

用户体验

  • 实时看到导入进度
  • 知道正在处理什么
  • 中断时有明确反馈
  • 日志便于排查问题

开发调试

  • 日志详细便于调试
  • 可以追踪每条记录
  • 快速定位性能瓶颈

现在重新编译并测试,应该能看到实时的进度更新和详细的处理日志了! 🚀