guoyu/_已清理文件备份_周六 22512/md/用户导入班级验证优化.md
2025-12-06 20:11:36 +08:00

9.8 KiB
Raw Blame History

用户导入班级验证优化说明

🎯 需求说明

用户要求

  1. 不要在导入前就报错中断
  2. 优先完成导入任务
  3. 遇到班级不存在的记录,跳过该条记录
  4. 继续导入其他记录
  5. 最后在导入结果中统一显示失败的记录和原因

实现方案

方案:逐条验证 + 异常捕获

核心逻辑

  1. 在处理每个用户时,在插入用户之前验证班级是否存在
  2. 如果班级不存在,抛出异常
  3. 外层catch捕获异常记录到失败信息中
  4. 继续处理下一个用户
  5. 最后统一显示导入结果

为什么在插入前验证?

  • 避免用户已插入但班级分配失败
  • 保证数据一致性
  • 失败的用户不会被导入到系统

🔧 修改内容

修改1移除Controller中的预验证

文件: StudyClassUserController.java

移除的代码:

// 预先验证所有班级是否存在
Set<String> uniqueClassNames = new HashSet<>();
// ... 收集班级名称
Map<String, Long> existingClasses = classUserService.getClassNameToIdMap();
// ... 检查班级
if (!missingClasses.isEmpty())
{
    throw new ServiceException("导入失败:...");
}

原因: 不要在导入前就中断整个流程


修改2添加逐条验证逻辑

文件: StudyClassUserServiceImpl.java

添加的代码:

// 预先验证班级是否存在(在插入/更新用户之前)
if (StringUtils.isNotEmpty(user.getRemark()))
{
    String remark = user.getRemark();
    int idx = remark.indexOf("班级名称:");
    if (idx >= 0)
    {
        String className = remark.substring(idx + 5).trim();
        if (StringUtils.isNotEmpty(className))
        {
            Long classId = classNameToIdMap.get(className);
            if (classId == null)
            {
                // 班级不存在,抛出异常
                throw new ServiceException("信息编号[" + infoNoStr + "]:班级 [" + className + "] 不存在,请先创建该班级");
            }
        }
    }
}

// 验证通过后,再插入/更新用户
SysUser u = userMapper.selectUserById(infoNo);
if (StringUtils.isNull(u))
{
    // 插入用户
    userMapper.insertUser(user);
    // ... 分配班级
}

关键点:

  • 验证在插入用户之前
  • 如果班级不存在,用户不会被插入
  • 异常会被外层catch捕获

修改3优化异常处理

文件: StudyClassUserServiceImpl.java

班级分配失败时的异常:

else
{
    // 班级不存在,抛出异常
    throw new ServiceException("班级 [" + className + "] 不存在,请先创建该班级");
}

作用: 作为双重保险,防止遗漏


🔄 完整流程

导入流程图

开始导入
  ↓
解析Excel100条记录
  ↓
开始逐条处理
  ↓
┌─────────────────────┐
│ 处理第1条张三     │
│ 班级:一班          │
│ ↓                   │
│ 验证班级是否存在    │
│ ✅ 一班存在         │
│ ↓                   │
│ 插入用户            │
│ ↓                   │
│ 分配班级            │
│ ↓                   │
│ ✅ 导入成功         │
└─────────────────────┘
  ↓
┌─────────────────────┐
│ 处理第2条李四     │
│ 班级:三班          │
│ ↓                   │
│ 验证班级是否存在    │
│ ❌ 三班不存在       │
│ ↓                   │
│ 抛出异常            │
│ ↓                   │
│ catch捕获异常       │
│ ↓                   │
│ 记录到errorMsg    │
│ "班级[三班]不存在"  │
│ ↓                   │
│ ❌ 导入失败         │
│ ❌ 用户未插入       │
└─────────────────────┘
  ↓
┌─────────────────────┐
│ 处理第3条王五     │
│ 班级:二班          │
│ ↓                   │
│ 验证班级是否存在    │
│ ✅ 二班存在         │
│ ↓                   │
│ 插入用户            │
│ ↓                   │
│ 分配班级            │
│ ↓                   │
│ ✅ 导入成功         │
└─────────────────────┘
  ↓
... 继续处理其他记录 ...
  ↓
所有记录处理完成
  ↓
生成导入结果:
  - 成功2条
  - 失败1条
  - 失败详情:
    1、信息编号 1002罪犯姓名 李四
       失败原因:班级 [三班] 不存在,请先创建该班级

📊 导入结果示例

示例1部分失败

Excel数据

信息编号 | 姓名 | 监区 | 班级
1001    | 张三 | A区  | 一班
1002    | 李四 | B区  | 三班
1003    | 王五 | C区  | 二班
1004    | 赵六 | D区  | 四班

数据库班级: 一班、二班(没有三班、四班)

导入结果:

导入完成!
新增: 2 条
更新: 0 条
失败: 2 条

失败详情:
1、信息编号 1002罪犯姓名 李四
   失败原因:信息编号[1002]:班级 [三班] 不存在,请先创建该班级
   
2、信息编号 1004罪犯姓名 赵六
   失败原因:信息编号[1004]:班级 [四班] 不存在,请先创建该班级

数据库结果:

  • 张三导入成功,分配到一班
  • 李四导入失败,未插入数据库
  • 王五导入成功,分配到二班
  • 赵六导入失败,未插入数据库

示例2全部成功

Excel数据

信息编号 | 姓名 | 监区 | 班级
1001    | 张三 | A区  | 一班
1002    | 李四 | B区  | 二班

数据库班级: 一班、二班

导入结果:

导入完成!
新增: 2 条
更新: 0 条
失败: 0 条

示例3部分无班级

Excel数据

信息编号 | 姓名 | 监区 | 班级
1001    | 张三 | A区  | 一班
1002    | 李四 | B区  | (空)
1003    | 王五 | C区  | 三班

数据库班级: 一班、二班(没有三班)

导入结果:

导入完成!
新增: 2 条
更新: 0 条
失败: 1 条

失败详情:
1、信息编号 1003罪犯姓名 王五
   失败原因:信息编号[1003]:班级 [三班] 不存在,请先创建该班级

数据库结果:

  • 张三导入成功,分配到一班
  • 李四导入成功,不分配班级(班级为空不验证)
  • 王五导入失败,未插入数据库

⚠️ 重要说明

1. 验证时机

  • 在插入/更新用户之前验证班级
  • 验证失败时,用户不会被插入/更新
  • 保证数据一致性

2. 空班级处理

  • 班级为空时,不进行验证
  • 用户可以导入成功,只是不分配班级

3. 异常处理

  • 每条记录的异常独立处理
  • 一条记录失败不影响其他记录
  • 所有失败记录统一显示

4. 错误信息格式

信息编号[1002]:班级 [三班] 不存在,请先创建该班级

包含信息:

  • 信息编号:方便定位是哪条记录
  • 班级名称:明确哪个班级不存在
  • 操作建议:提示用户先创建班级

🧪 测试场景

测试1混合场景

Excel
- 张三 → 一班(存在)
- 李四 → 三班(不存在)
- 王五 → 二班(存在)
- 赵六 → 四班(不存在)
- 孙七 → (空)

预期结果:
✅ 张三导入成功
❌ 李四导入失败(班级不存在)
✅ 王五导入成功
❌ 赵六导入失败(班级不存在)
✅ 孙七导入成功(无班级)

统计:
- 成功3条
- 失败2条
- 失败详情列出李四和赵六

🚀 部署步骤

1. 重新编译后端

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

2. 重启后端服务

3. 测试导入

  1. 创建"一班"和"二班"
  2. 准备Excel包含一班、二班、三班
  3. 执行导入
  4. 查看导入结果:
    • 一班和二班的用户导入成功
    • 三班的用户导入失败,显示错误信息

📋 验收标准

功能验收

  • 班级存在时,用户导入成功
  • 班级不存在时,该用户导入失败
  • 失败的用户不会被插入到数据库
  • 一个用户失败不影响其他用户
  • 导入结果显示成功数和失败数
  • 失败详情包含信息编号、姓名和失败原因
  • 班级为空时,用户可以导入成功

数据一致性验收

  • 失败的用户在sys_user表中不存在
  • 失败的用户在student_class表中不存在
  • 成功的用户正确分配到指定班级
  • 没有"用户存在但班级未分配"的情况

用户体验验收

  • 导入过程不中断
  • 导入结果一次性展示
  • 错误信息清晰明确
  • 可以根据错误信息快速定位问题

💡 优化建议

建议1批量创建班级

在导入结果中提供"创建缺失的班级"按钮,一键创建所有不存在的班级

建议2Excel模板

提供Excel模板下载包含当前系统中所有班级的下拉列表

建议3导入预检

在上传Excel后、开始导入前先显示预检结果哪些班级不存在


总结

优化效果

  • 导入不会因个别记录失败而中断
  • 成功的记录正常导入,失败的记录清晰展示
  • 数据一致性得到保证
  • 用户体验更友好

技术要点

  • 逐条验证而非批量验证
  • 验证在插入之前而非之后
  • 异常独立处理而非全局处理
  • 结果统一展示而非即时报错