cba2ad3b3b
2、调整运单
8.4 KiB
8.4 KiB
运输计划导入增强校验说明
修改日期
2026-09-08
一、导入逻辑变更
原有逻辑
- 逐条导入,遇错即停
- 部分数据可能已入库
- 错误信息简单
新逻辑(参考 /base/port-terminal)
-
第一阶段:全部校验
- 先校验所有数据
- 收集所有错误信息
- 不进行任何数据库操作
-
第二阶段:批量导入
- 仅当所有数据校验通过后才导入
- 任何一条数据有错误,全部回滚
- 保证数据一致性
-
错误处理
- 导出包含错误信息的Excel
- 每条错误数据标注具体错误原因
- 支持多个错误信息(编号列表)
二、详细校验规则
1. 必填字段校验
| 字段 | 校验规则 | 错误提示 |
|---|---|---|
| *计划名称 | 不能为空 | 计划名称不能为空 |
| *运输类型 | 不能为空 | 运输类型不能为空 |
| *发货地址 | 不能为空 | 发货地址不能为空 |
| *到货地址 | 不能为空 | 到货地址不能为空 |
| *货物类型 | 不能为空 | 货物类型不能为空 |
2. 枚举值校验
运输类型
允许值:
- 公路整车
- 公路配载/零担
- 铁路运输
- 水路运输
- 跨境海运
- 航空运输
错误提示: 运输类型需系统枚举值(公路整车、公路配载/零担、铁路运输、水路运输、跨境海运、航空运输)
计量单位
常用值:
- 吨、千克、立方米、件、车、箱、托盘、个、套、台
错误提示: 计量单位不存在
3. 唯一性校验
计划名称(当前组织下不重复)
- 检查本次导入数据中的重复
- 检查数据库中当前组织的重复
- 错误提示:
- 计划名称在导入数据中重复
- 计划名称在当前组织下已存在
4. 格式校验
联系电话
规则: 11位数字
- 发货联系人电话
- 收货联系人电话
错误提示:
- 发货联系人电话格式不正确(需11位数字)
- 收货联系人电话格式不正确(需11位数字)
日期时间
格式: YYYY-MM-DD
- 计划开始时间(非必填)
- 计划结束时间(非必填)
逻辑校验: 计划结束时间不得早于计划开始时间
错误提示:
- 计划开始时间格式必须为 YYYY-MM-DD
- 计划结束时间格式必须为 YYYY-MM-DD
- 计划结束时间不得早于计划开始时间
5. 数值校验
数量
规则: 必须为正数或零 错误提示: 数量必须为正数
里程(km)
规则: 必须为正数或零 错误提示: 里程必须为正数
6. 长度校验
| 字段 | 最大长度 | 错误提示 |
|---|---|---|
| 计划名称 | 255字符 | 计划名称不能超过255个字符 |
| 发货地址 | 255字符 | 发货地址不能超过255个字符 |
| 到货地址 | 255字符 | 到货地址不能超过255个字符 |
| 发货联系人 | 255字符 | 发货联系人不能超过255个字符 |
| 收货联系人 | 255字符 | 收货联系人不能超过255个字符 |
| 同一计划标识号 | 255字符 | 同一计划标识号不能超过255个字符 |
| 备注 | 500字符 | 备注不能超过500个字符 |
7. 同一计划标识号校验
用途: 当需要导入的计划的货物包含多个时,需拆分多行,并填写该标识,来标记多行为同一计划
校验规则:
- 同一标识号下的所有记录应保持以下字段一致:
- 计划名称
- 运输类型
- 发货地址
- 到货地址
警告提示: 注意:同一计划标识号应保持计划名称、运输类型、发货地址、到货地址一致
8. 地址匹配校验(警告级别)
规则: 地址应能匹配到系统地址库
警告提示:
- 警告:发货地址未匹配到地址库,轨迹回放将受影响
- 警告:到货地址未匹配到地址库,轨迹回放将受影响
说明: 此为警告级别,不阻止导入,但会影响后续功能
三、错误信息格式
单条错误
1. 计划名称不能为空
多条错误
1. 计划名称不能为空
2. 运输类型需系统枚举值(公路整车、公路配载/零担、铁路运输、水路运输、跨境海运、航空运输)
3. 发货联系人电话格式不正确(需11位数字)
四、导入流程
用户操作流程
- 下载导入模板
- 填写计划数据
- 上传Excel文件
- 等待校验结果
系统处理流程
情况1:所有数据校验通过
解析Excel → 全部校验(通过) → 批量导入 → 提示成功
情况2:存在校验错误
解析Excel → 全部校验(失败) → 生成错误Excel → 下载错误明细
- 不会导入任何数据
- 用户下载包含错误信息的Excel
- 修正后重新导入
五、后端实现要点
1. 两阶段提交
@Transactional(rollbackFor = Exception.class)
public List<TransportPlanImportExcel> importTransportPlan(...) {
// 第一阶段:全部校验
Map<Integer, TransportPlanImportExcel> errorMap = new TreeMap<>();
for (int index = 0; index < data.size(); index++) {
List<String> errors = validateImportExcel(excel, ...);
if (Func.isNotEmpty(errors)) {
excel.setErrorMessage(formatErrorMessage(errors));
errorMap.put(index, excel);
}
}
// 如果有错误,回滚事务
if (Func.isNotEmpty(errorMap)) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return new ArrayList<>(errorMap.values());
}
// 第二阶段:批量导入
for (TransportPlan plan : importPlans) {
save(plan);
}
return new ArrayList<>();
}
2. 错误收集器
- 使用
TreeMap保持顺序 - 索引作为key,保持与Excel行号对应
- 错误信息格式化为编号列表
3. 校验方法
private List<String> validateImportExcel(...) {
List<String> errors = new ArrayList<>();
// 收集所有错误,不立即抛出异常
if (condition) {
errors.add("错误信息");
}
return errors;
}
六、前端修改(transport-plan-import.vue)
无需修改
前端保持原有逻辑,后端返回的错误Excel会自动触发下载
七、测试用例
测试用例1:必填字段缺失
输入: 计划名称为空 预期:
- 不导入任何数据
- 错误信息:计划名称不能为空
测试用例2:运输类型枚举值错误
输入: 运输类型 = "陆运" 预期:
- 不导入任何数据
- 错误信息:运输类型需系统枚举值
测试用例3:电话格式错误
输入: 发货联系人电话 = "12345" 预期:
- 不导入任何数据
- 错误信息:发货联系人电话格式不正确(需11位数字)
测试用例4:计划名称重复
输入: 两条数据的计划名称相同 预期:
- 不导入任何数据
- 错误信息:计划名称在导入数据中重复
测试用例5:部分数据错误
输入: 10条数据,第5条有错误 预期:
- 不导入任何数据(包括前4条正确的)
- 仅第5条有错误信息
测试用例6:多个错误
输入: 一条数据同时缺少计划名称和运输类型 预期:
1. 计划名称不能为空
2. 运输类型不能为空
测试用例7:同一计划标识号
输入: 3条数据,同一标识号,货物信息不同 预期:
- 可以导入
- 3条记录关联到同一计划标识号
八、与 port-terminal 导入的对比
| 特性 | port-terminal | transport-plan |
|---|---|---|
| 两阶段校验 | ✓ | ✓ |
| 错误即回滚 | ✓ | ✓ |
| 错误信息编号 | ✓ | ✓ |
| 唯一性校验 | ✓ | ✓ |
| 枚举值校验 | ✓ | ✓ |
| 格式校验 | ✓ | ✓ |
| 批量导入 | ✓ | ✓ |
九、后续优化建议
-
地址匹配校验
- 实现发货地址和到货地址的地址库匹配
- 返回警告信息(不阻止导入)
-
货物类型智能匹配
- 根据货物名称自动匹配货物类型
- 未匹配到时归为"其他"类
-
同一计划标识号一致性校验
- 完整实现同一标识号的字段一致性检查
- 在第一阶段校验中完成
-
计量单位字典化
- 从数据字典读取有效的计量单位列表
- 支持自定义扩展
-
导入预览
- 前端增加导入预览功能
- 用户可在导入前查看解析结果