diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/excel/ImportFailureException.java b/blade-common/src/main/java/org/springblade/common/excel/ImportFailureException.java similarity index 72% rename from blade-service/blade-system/src/main/java/org/springblade/system/excel/ImportFailureException.java rename to blade-common/src/main/java/org/springblade/common/excel/ImportFailureException.java index 0277ec01..6065ce0f 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/excel/ImportFailureException.java +++ b/blade-common/src/main/java/org/springblade/common/excel/ImportFailureException.java @@ -23,7 +23,7 @@ *

* Author: Chill Zhuang (bladejava@qq.com) */ -package org.springblade.system.excel; +package org.springblade.common.excel; import org.springblade.core.log.exception.ServiceException; @@ -33,8 +33,14 @@ import java.util.List; /** * 导入失败异常,携带失败明细用于导出原表并标注错误。 *

- * 批量导入采用「全失败即整批回滚」语义:任一行校验失败都会抛出本异常触发事务回滚, - * 失败明细在抛异常前已收集完毕,因此回滚不影响明细的内容。 + * 批量导入采用「任一行失败即整批回滚」语义:循环内先收集完全部错误明细, + * 再抛出本异常触发事务回滚。明细在抛异常前已收集完毕,因此回滚不影响明细内容。 + *

+ * 注意:仅标注 {@code @Transactional} 并不足够。若循环内把异常吞掉(catch 后 + * 只往 errorList 塞数据并正常 return),方法会正常返回,Spring 会照常提交事务。 + * 必须抛出异常才能让事务真正回滚。 + *

+ * 本类位于 blade-common,供 blade-system 与 blade-transport 等模块共用。 * * @author Chill */ diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/controller/CargoTypeController.java b/blade-service/blade-system/src/main/java/org/springblade/system/controller/CargoTypeController.java index 745968b5..616e1ae6 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/controller/CargoTypeController.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/controller/CargoTypeController.java @@ -46,9 +46,9 @@ import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.DateUtil; import org.springblade.core.tool.utils.Func; import org.springblade.common.excel.ImportFailureExcelUtil; +import org.springblade.common.excel.ImportFailureException; import org.springblade.system.excel.CargoTypeExcel; import org.springblade.system.excel.CargoTypeExportExcel; -import org.springblade.system.excel.CargoTypeImportFailureExcel; import org.springblade.system.pojo.entity.CargoType; import org.springblade.system.pojo.vo.CargoTypeVO; import org.springblade.system.service.ICargoTypeService; @@ -156,15 +156,32 @@ public class CargoTypeController extends BladeController { @ApiOperationSupport(order = 7) @Operation(summary = "导入货物类型", description = "传入excel") public R importCargoType(MultipartFile file, HttpServletResponse response) { - List data = ExcelUtil.read(file, CargoTypeExcel.class); - List failureList = cargoTypeService.importCargoType(data); - if (Func.isNotEmpty(failureList)) { - ImportFailureExcelUtil.export(response, "货物类型导入失败明细" + DateUtil.time(), "导入失败明细", failureList, CargoTypeExcel.class); + if (file == null || file.isEmpty()) { + return R.fail("上传文件不能为空"); + } + String fileName = Func.toStrWithEmpty(file.getOriginalFilename(), "").toLowerCase(); + if (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx")) { + return R.fail("请上传 .xls,.xlsx 标准格式文件"); + } + try { + cargoTypeService.importCargoType(ExcelUtil.read(file, CargoTypeExcel.class)); + } catch (ImportFailureException exception) { + // 任一行失败即整批回滚,导出原表全部数据并标注错误,用户修正后重新导入。 + exportFailure(response, exception.getFailureList()); return null; } return R.success("导入数据成功"); } + /** + * 导出导入失败明细,内容为原表全部数据并在末尾追加失败原因列。 + *

+ * 失败数据仅标红出错单元格与失败原因列,表头保持默认样式。 + */ + private void exportFailure(HttpServletResponse response, List failureList) { + ImportFailureExcelUtil.exportFailureReasonOnly(response, "货物类型导入失败明细" + DateUtil.time(), "导入失败明细", failureList, CargoTypeExcel.class); + } + /** * 导出货物类型 */ diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/controller/PortTerminalController.java b/blade-service/blade-system/src/main/java/org/springblade/system/controller/PortTerminalController.java index 0639b52d..8c19eedc 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/controller/PortTerminalController.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/controller/PortTerminalController.java @@ -44,7 +44,7 @@ import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.DateUtil; import org.springblade.core.tool.utils.Func; import org.springblade.common.excel.ImportFailureExcelUtil; -import org.springblade.system.excel.ImportFailureException; +import org.springblade.common.excel.ImportFailureException; import org.springblade.system.excel.PortTerminalExcel; import org.springblade.system.excel.PortTerminalExportExcel; import org.springblade.system.excel.PortTerminalImporter; diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/CargoTypeServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/CargoTypeServiceImpl.java index e7b97e2b..a1fc4f74 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/CargoTypeServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/CargoTypeServiceImpl.java @@ -29,6 +29,7 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import org.springblade.common.excel.ImportFailureException; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.tool.utils.Func; @@ -134,10 +135,14 @@ public class CargoTypeServiceImpl extends BaseServiceImpl importCargoType(List data) { if (Func.isEmpty(data)) { throw new ServiceException("导入数据不能为空"); } + // 全量校验:任何一行失败都整批回滚,因此先收集所有错误再统一抛出。 + // 注意不能只往 errorList 里塞数据就 return——异常被吞掉后方法会正常返回, + // Spring 会照常提交事务,@Transactional 起不到回滚作用。 List failureList = new ArrayList<>(); for (int index = 0; index < data.size(); index++) { CargoTypeExcel excel = data.get(index); @@ -152,6 +157,11 @@ public class CargoTypeServiceImpl extends BaseServiceImpl