diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysRoleController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysRoleController.java index e6afa3c07..3cd8d1ef0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysRoleController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysRoleController.java @@ -5,6 +5,7 @@ import cn.hutool.core.lang.tree.Tree; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; +import org.dromara.common.excel.core.ExcelResult; import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; @@ -16,13 +17,18 @@ import org.dromara.system.domain.bo.SysDeptBo; import org.dromara.system.domain.bo.SysRoleBo; import org.dromara.system.domain.bo.SysUserBo; import org.dromara.system.domain.vo.SysRoleVo; +import org.dromara.system.domain.vo.SysUserRoleImportVo; import org.dromara.system.domain.vo.SysUserVo; +import org.dromara.system.listener.SysUserRoleImportListener; import org.dromara.system.service.ISysDeptService; import org.dromara.system.service.ISysRoleService; import org.dromara.system.service.ISysUserService; +import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import java.util.ArrayList; import java.util.List; /** @@ -60,6 +66,28 @@ public class SysRoleController extends BaseController { ExcelUtil.exportExcel(list, "角色数据", SysRoleVo.class, response); } + /** + * 导入用户角色数据(分配或取消授权) + * + * @param file 导入文件 + * @param assign true = 分配用户,false = 取消授权 + */ + @Log(title = "角色管理", businessType = BusinessType.IMPORT) + @SaCheckPermission("system:role:import") + @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public R importData(@RequestPart("file") MultipartFile file, @RequestParam(value = "assign", required = true) boolean assign) throws Exception { + ExcelResult result = ExcelUtil.importExcel(file.getInputStream(), SysUserRoleImportVo.class, new SysUserRoleImportListener(assign)); + return R.ok(result.getAnalysis()); + } + + /** + * 获取角色导入模板 + */ + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) { + ExcelUtil.exportExcel(new ArrayList<>(), "角色数据", SysUserRoleImportVo.class, response); + } + /** * 根据角色编号获取详细信息 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserRoleImportVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserRoleImportVo.java new file mode 100644 index 000000000..4254f75eb --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserRoleImportVo.java @@ -0,0 +1,40 @@ +package org.dromara.system.domain.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 用户角色导入对象 + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +// @Accessors(chain = true) // 导入不允许使用 会找不到set方法 +public class SysUserRoleImportVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 用户账号 + */ + @ExcelProperty(value = "用户账号") + @NotBlank(message = "用户账号不能为空") + @Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符") + private String userName; + + /** + * 角色权限标识 + */ + @ExcelProperty(value = "角色权限") + @NotBlank(message = "角色权限不能为空") + private String roleKey; + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserRoleImportListener.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserRoleImportListener.java new file mode 100644 index 000000000..32dfa8cd1 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserRoleImportListener.java @@ -0,0 +1,143 @@ +package org.dromara.system.listener; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HtmlUtil; +import cn.idev.excel.context.AnalysisContext; +import cn.idev.excel.event.AnalysisEventListener; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.ValidatorUtils; +import org.dromara.common.excel.core.ExcelListener; +import org.dromara.common.excel.core.ExcelResult; +import org.dromara.system.domain.SysUserRole; +import org.dromara.system.domain.vo.SysRoleVo; +import org.dromara.system.domain.vo.SysUserRoleImportVo; +import org.dromara.system.domain.vo.SysUserVo; +import org.dromara.system.mapper.SysUserRoleMapper; +import org.dromara.system.service.ISysRoleService; +import org.dromara.system.service.ISysUserService; + +import java.util.List; +import java.util.Map; + +/** + * 系统用户自定义导入 + * + * @author Lion Li + */ +@Slf4j +public class SysUserRoleImportListener extends AnalysisEventListener implements ExcelListener { + + private final ISysUserService userService; + private final ISysRoleService roleService; + private final SysUserRoleMapper userRoleMapper; + + private final Boolean assign; + private final Map roleKeyIdMap; + + private int successNum = 0; + private int failureNum = 0; + private final StringBuilder successMsg = new StringBuilder(); + private final StringBuilder failureMsg = new StringBuilder(); + + public SysUserRoleImportListener(Boolean assign) { + this.userService = SpringUtils.getBean(ISysUserService.class); + this.roleService = SpringUtils.getBean(ISysRoleService.class); + this.userRoleMapper = SpringUtils.getBean(SysUserRoleMapper.class); + this.assign = assign; + this.roleKeyIdMap = StreamUtils.toMap(roleService.selectRoleAll(), SysRoleVo::getRoleKey, SysRoleVo::getRoleId); + } + + @Override + public void invoke(SysUserRoleImportVo record, AnalysisContext context) { + try { + ValidatorUtils.validate(record); + + Long roleId = roleKeyIdMap.get(record.getRoleKey()); + if (ObjectUtil.isNull(roleId)) { + failureNum++; + failureMsg.append("
").append(failureNum).append("、角色标识 [").append(record.getRoleKey()).append("] 不存在"); + return; + } else { + roleService.checkRoleDataScope(roleId); + } + + SysUserVo sysUser = this.userService.selectUserByUserName(record.getUserName()); + if (ObjectUtil.isNull(sysUser)) { + failureNum++; + failureMsg.append("
").append(failureNum).append("、账号 [").append(record.getUserName()).append("] 不存在"); + return; + } + Long userId = sysUser.getUserId(); + SysUserRole userRole = new SysUserRole(); + userRole.setRoleId(roleId); + userRole.setUserId(userId); + if (assign) { + Long count = userRoleMapper.selectCount(new LambdaQueryWrapper() + .eq(SysUserRole::getRoleId, roleId) + .eq(SysUserRole::getUserId, userId) + ); + if (count == 0) { + userRoleMapper.insert(userRole); + successMsg.append("
").append(++successNum).append("、账号 [").append(record.getUserName()).append("] 分配角色成功"); + } else { + successMsg.append("
").append(++successNum).append("、账号 [").append(record.getUserName()).append("] 已存在角色,无需重复分配"); + } + } else { + userRoleMapper.delete(new LambdaQueryWrapper() + .eq(SysUserRole::getRoleId, roleId) + .eq(SysUserRole::getUserId, userId) + ); + successNum++; + successMsg.append("
").append(successNum).append("、账号 [").append(record.getUserName()).append("] 取消角色成功"); + } + + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、账号 " + HtmlUtil.cleanHtmlTag(ObjectUtil.defaultIfNull(record.getUserName(), "未知账号")) + " 操作失败:"; + String message = e.getMessage(); + if (e instanceof ConstraintViolationException cvException) { + message = StreamUtils.join(cvException.getConstraintViolations(), ConstraintViolation::getMessage, ", "); + } + failureMsg.append(msg).append(message); + log.error(msg, e); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + + } + + @Override + public ExcelResult getExcelResult() { + return new ExcelResult<>() { + + @Override + public String getAnalysis() { + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } else { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + @Override + public List getList() { + return null; + } + + @Override + public List getErrorList() { + return null; + } + }; + } +}