From 9ff88c4a749c5d8b3cfdab59d4298534bde73879 Mon Sep 17 00:00:00 2001 From: Theo <971366405@qq.com> Date: Tue, 14 Jan 2025 11:03:53 +0800 Subject: [PATCH] =?UTF-8?q?refactor(system):=20=E9=87=8D=E6=9E=84=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=AF=BC=E5=85=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 ExcelResult 类用于封装导入结果 - 修改 ExcelUtils 类,移除返回值类型 - 更新 UserController 中的用户导入接口,使用 ExcelResult 返回结果- 重构 UserImportListener 类,优化数据校验和处理逻辑 --- .../boot/common/result/ExcelResult.java | 43 +++++ .../youlai/boot/common/util/ExcelUtils.java | 5 +- .../system/controller/UserController.java | 7 +- .../system/listener/UserImportListener.java | 175 +++++++++++------- 4 files changed, 155 insertions(+), 75 deletions(-) create mode 100644 src/main/java/com/youlai/boot/common/result/ExcelResult.java diff --git a/src/main/java/com/youlai/boot/common/result/ExcelResult.java b/src/main/java/com/youlai/boot/common/result/ExcelResult.java new file mode 100644 index 00000000..d9d6590a --- /dev/null +++ b/src/main/java/com/youlai/boot/common/result/ExcelResult.java @@ -0,0 +1,43 @@ +package com.youlai.boot.common.result; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * Excel导出响应结构体 + * + * @author Theo + * @since 2025/1/14 11:46:08 + */ +@Data +public class ExcelResult { + + /** + * 响应码,来确定是否导入成功 + */ + private String code; + + /** + * 有效条数 + */ + private Integer validCount; + + /** + * 无效条数 + */ + private Integer invalidCount; + + /** + * 错误提示信息 + */ + private List messageList; + + public ExcelResult() { + this.code = ResultCode.SUCCESS.getCode(); + this.validCount = 0; + this.invalidCount = 0; + this.messageList = new ArrayList<>(); + } +} diff --git a/src/main/java/com/youlai/boot/common/util/ExcelUtils.java b/src/main/java/com/youlai/boot/common/util/ExcelUtils.java index 6ebaf950..6be58cfc 100644 --- a/src/main/java/com/youlai/boot/common/util/ExcelUtils.java +++ b/src/main/java/com/youlai/boot/common/util/ExcelUtils.java @@ -1,7 +1,7 @@ package com.youlai.boot.common.util; import com.alibaba.excel.EasyExcel; -import com.youlai.boot.common.base.BaseAnalysisEventListener; +import com.alibaba.excel.event.AnalysisEventListener; import java.io.InputStream; @@ -13,8 +13,7 @@ import java.io.InputStream; */ public class ExcelUtils { - public static String importExcel(InputStream is, Class clazz, BaseAnalysisEventListener listener) { + public static void importExcel(InputStream is, Class clazz, AnalysisEventListener listener) { EasyExcel.read(is, clazz, listener).sheet().doRead(); - return listener.getMsg(); } } diff --git a/src/main/java/com/youlai/boot/system/controller/UserController.java b/src/main/java/com/youlai/boot/system/controller/UserController.java index 88af5819..0b5e39fa 100644 --- a/src/main/java/com/youlai/boot/system/controller/UserController.java +++ b/src/main/java/com/youlai/boot/system/controller/UserController.java @@ -8,6 +8,7 @@ import com.youlai.boot.common.annotation.Log; import com.youlai.boot.common.annotation.RepeatSubmit; import com.youlai.boot.common.enums.LogModuleEnum; import com.youlai.boot.common.model.Option; +import com.youlai.boot.common.result.ExcelResult; import com.youlai.boot.common.result.PageResult; import com.youlai.boot.common.result.Result; import com.youlai.boot.common.util.ExcelUtils; @@ -152,10 +153,10 @@ public class UserController { @Operation(summary = "导入用户") @PostMapping("/import") @Log(value = "导入用户", module = LogModuleEnum.USER) - public Result importUsers(MultipartFile file) throws IOException { + public Result importUsers(MultipartFile file) throws IOException { UserImportListener listener = new UserImportListener(); - String msg = ExcelUtils.importExcel(file.getInputStream(), UserImportDTO.class, listener); - return Result.success(msg); + ExcelUtils.importExcel(file.getInputStream(), UserImportDTO.class, listener); + return Result.success(listener.getExcelResult()); } @Operation(summary = "导出用户") diff --git a/src/main/java/com/youlai/boot/system/listener/UserImportListener.java b/src/main/java/com/youlai/boot/system/listener/UserImportListener.java index 7fbf7f4b..fe65b432 100644 --- a/src/main/java/com/youlai/boot/system/listener/UserImportListener.java +++ b/src/main/java/com/youlai/boot/system/listener/UserImportListener.java @@ -7,19 +7,22 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.json.JSONUtil; import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.youlai.boot.common.base.BaseAnalysisEventListener; -import com.youlai.boot.system.enums.DictCodeEnum; -import com.youlai.boot.system.model.entity.*; -import com.youlai.boot.common.base.IBaseEnum; import com.youlai.boot.common.constant.SystemConstants; import com.youlai.boot.common.enums.StatusEnum; +import com.youlai.boot.common.result.ExcelResult; import com.youlai.boot.system.converter.UserConverter; +import com.youlai.boot.system.enums.DictCodeEnum; import com.youlai.boot.system.model.dto.UserImportDTO; +import com.youlai.boot.system.model.entity.*; import com.youlai.boot.system.service.*; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -32,34 +35,45 @@ import java.util.stream.Collectors; * @since 2022/4/10 */ @Slf4j -public class UserImportListener extends BaseAnalysisEventListener { +public class UserImportListener extends AnalysisEventListener { - - // 有效条数 - private int validCount; - - // 无效条数 - private int invalidCount; - - // 导入返回信息 - StringBuilder msg = new StringBuilder(); + /** + * excel导入结果实体 + */ + @Getter + private ExcelResult excelResult; private final UserService userService; private final PasswordEncoder passwordEncoder; private final UserConverter userConverter; - private final RoleService roleService; private final UserRoleService userRoleService; - private final DeptService deptService; - private final DictDataService dictDataService; + private final List roleList; + private final List deptList; + private final List genderDataList; + + /** + * 当前行 + */ + private Integer currentRow = 1; + + /** + * 构造方法 + *

在构造方法中给需要查询的内容查询好,尽量避免每条数据查询一次

+ */ public UserImportListener() { this.userService = SpringUtil.getBean(UserService.class); this.passwordEncoder = SpringUtil.getBean(PasswordEncoder.class); - this.roleService = SpringUtil.getBean(RoleService.class); this.userRoleService = SpringUtil.getBean(UserRoleService.class); - this.deptService = SpringUtil.getBean(DeptService.class); - this.dictDataService = SpringUtil.getBean(DictDataService.class); this.userConverter = SpringUtil.getBean(UserConverter.class); + this.roleList = SpringUtil.getBean(RoleService.class) + .list(new LambdaQueryWrapper().eq(Role::getStatus, StatusEnum.ENABLE.getValue()) + .select(Role::getId, Role::getCode)); + this.deptList = SpringUtil.getBean(DeptService.class) + .list(new LambdaQueryWrapper().select(Dept::getId, Dept::getCode)); + this.genderDataList = SpringUtil.getBean(DictDataService.class) + .list(new LambdaQueryWrapper().eq(DictData::getDictCode, DictCodeEnum.GENDER.getValue())); + this.excelResult = new ExcelResult(); } /** @@ -73,78 +87,56 @@ public class UserImportListener extends BaseAnalysisEventListener @Override public void invoke(UserImportDTO userImportDTO, AnalysisContext analysisContext) { log.info("解析到一条用户数据:{}", JSONUtil.toJsonStr(userImportDTO)); - // 校验数据 - StringBuilder validationMsg = new StringBuilder(); + boolean validation = true; + String errorMsg = "第" + currentRow + "行数据校验失败:"; String username = userImportDTO.getUsername(); if (StrUtil.isBlank(username)) { - validationMsg.append("用户名为空;"); + errorMsg +="用户名为空;"; + validation = false; } else { long count = userService.count(new LambdaQueryWrapper().eq(User::getUsername, username)); if (count > 0) { - validationMsg.append("用户名已存在;"); + errorMsg +="用户名已存在;"; + validation = false; } } String nickname = userImportDTO.getNickname(); if (StrUtil.isBlank(nickname)) { - validationMsg.append("用户昵称为空;"); + errorMsg +="用户昵称为空;"; + validation = false; } String mobile = userImportDTO.getMobile(); if (StrUtil.isBlank(mobile)) { - validationMsg.append("手机号码为空;"); + errorMsg +="手机号码为空;"; + validation = false; } else { if (!Validator.isMobile(mobile)) { - validationMsg.append("手机号码不正确;"); + errorMsg +="手机号码不正确;"; + validation = false; } } - if (validationMsg.isEmpty()) { + if (validation) { // 校验通过,持久化至数据库 User entity = userConverter.toEntity(userImportDTO); entity.setPassword(passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD)); // 默认密码 // 性别逆向翻译 根据字典标签得到字典值 String genderLabel = userImportDTO.getGenderLabel(); - if (StrUtil.isNotBlank(genderLabel)) { - DictData dictData = dictDataService.getOne(new LambdaQueryWrapper() - .eq(DictData::getDictCode, DictCodeEnum.GENDER.getValue()) - .eq(DictData::getLabel, genderLabel) - .last("limit 1") - ); - if (dictData != null) { - Integer genderValue = Convert.toInt(dictData.getValue(),0); - entity.setGender(genderValue); - } - } + entity.setGender(getGenderValue(genderLabel)); // 角色解析 String roleCodes = userImportDTO.getRoleCodes(); - List roleIds = null; - if (StrUtil.isNotBlank(roleCodes)) { - roleIds = roleService.list( - new LambdaQueryWrapper() - .in(Role::getCode, (Object) roleCodes.split(",")) - .eq(Role::getStatus, StatusEnum.ENABLE.getValue()) - .select(Role::getId) - ).stream() - .map(Role::getId) - .collect(Collectors.toList()); - } + List roleIds = getRoleIds(roleCodes); // 部门解析 String deptCode = userImportDTO.getDeptCode(); - if (StrUtil.isNotBlank(deptCode)) { - Dept dept = deptService.getOne(new LambdaQueryWrapper().eq(Dept::getCode, deptCode) - .select(Dept::getId) - ); - if (dept != null) { - entity.setDeptId(dept.getId()); - } - } + entity.setDeptId(getDeptId(deptCode)); boolean saveResult = userService.save(entity); if (saveResult) { - validCount++; + excelResult.setValidCount(excelResult.getValidCount() + 1); // 保存用户角色关联 if (CollectionUtil.isNotEmpty(roleIds)) { List userRoles = roleIds.stream() @@ -153,16 +145,67 @@ public class UserImportListener extends BaseAnalysisEventListener userRoleService.saveBatch(userRoles); } } else { - invalidCount++; - msg.append("第").append(validCount + invalidCount).append("行数据保存失败;
"); + excelResult.setInvalidCount(excelResult.getInvalidCount() + 1); + errorMsg += "数据保存失败;"; + excelResult.getMessageList().add(errorMsg); } } else { - invalidCount++; - msg.append("第").append(validCount + invalidCount).append("行数据校验失败:").append(validationMsg).append("
"); + excelResult.setInvalidCount(excelResult.getInvalidCount() + 1); + excelResult.getMessageList().add(errorMsg); } + currentRow++; } + /** + * 根据角色编码获取角色ID + * + * @param roleCodes 角色编码 逗号分隔 + * @return 角色ID集合 + */ + private List getRoleIds(String roleCodes) { + if (StrUtil.isNotBlank(roleCodes)) { + String[] split = roleCodes.split(","); + if (split.length > 0) { + List roleIds = new ArrayList<>(); + for (String roleCode : split) { + this.roleList.stream().filter(r -> r.getCode().equals(roleCode)) + .findFirst().ifPresent(role -> roleIds.add(role.getId())); + } + return roleIds.stream().distinct().toList(); + } + } + return Collections.emptyList(); + } + + /** + * 根据部门编码获取部门ID + * + * @param deptCode 部门编码 + * @return 部门ID + */ + private Long getDeptId(String deptCode) { + if (StrUtil.isNotBlank(deptCode)) { + return this.deptList.stream().filter(r -> r.getCode().equals(deptCode)) + .findFirst().map(Dept::getId).orElse(null); + } + return null; + } + + /** + * 根据性别标签获取性别值 + * + * @param genderLabel 性别标签 + * @return 性别值 + */ + private Integer getGenderValue(String genderLabel) { + if (StrUtil.isNotBlank(genderLabel)) { + return this.genderDataList.stream().filter(r -> r.getLabel().equals(genderLabel)) + .findFirst().map(DictData::getValue).map(Convert::toInt).orElse(null); + } + return null; + } + /** * 所有数据解析完成会来调用 */ @@ -171,10 +214,4 @@ public class UserImportListener extends BaseAnalysisEventListener log.info("所有数据解析完成!"); } - - @Override - public String getMsg() { - // 总结信息 - return StrUtil.format("导入用户结束:成功{}条,失败{}条;
{}", validCount, invalidCount, msg); - } }