From 8969ad36ee20383e907b4406051f2af9ff74f2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=98=E7=BB=AA=E5=A3=AE?= <2235602974@qq.com> Date: Sat, 26 Mar 2022 16:05:44 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E8=A7=92=E8=89=B2=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=AF=BC=E5=85=A5=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pigx/admin/api/vo/RoleExcelVO.java | 56 +++++++++++++ .../admin/controller/SysRoleController.java | 27 +++++++ .../pigx/admin/service/SysRoleService.java | 17 ++++ .../service/impl/SysRoleServiceImpl.java | 76 ++++++++++++++++++ .../src/main/resources/file/role.xlsx | Bin 0 -> 8834 bytes 5 files changed, 176 insertions(+) create mode 100644 pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/RoleExcelVO.java create mode 100644 pigx-upms/pigx-upms-biz/src/main/resources/file/role.xlsx diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/RoleExcelVO.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/RoleExcelVO.java new file mode 100644 index 000000000..423ca3ac8 --- /dev/null +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/vo/RoleExcelVO.java @@ -0,0 +1,56 @@ +package com.pig4cloud.pigx.admin.api.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 角色excel 对应的实体 + * + * @author fxz + * @date 2022/3/21 + */ +@Data +@ColumnWidth(30) +public class RoleExcelVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @ExcelProperty("角色编号") + private Long roleId; + + /** + * 角色名称 + */ + @NotBlank(message = "角色名称不能为空") + @ExcelProperty("角色名称") + private String roleName; + + /** + * 角色标识 + */ + @NotBlank(message = "角色标识不能为空") + @ExcelProperty("角色标识") + private String roleCode; + + /** + * 角色描述 + */ + @NotBlank(message = "角色描述不能为空") + @ExcelProperty("角色描述") + private String roleDesc; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private LocalDateTime createTime; + +} diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysRoleController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysRoleController.java index 01ac623e6..ff94564e7 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysRoleController.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysRoleController.java @@ -24,15 +24,19 @@ import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.pig4cloud.pigx.admin.api.entity.SysRole; +import com.pig4cloud.pigx.admin.api.vo.RoleExcelVO; import com.pig4cloud.pigx.admin.api.vo.RoleVO; import com.pig4cloud.pigx.admin.service.SysRoleService; import com.pig4cloud.pigx.common.core.constant.CacheConstants; import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.excel.annotation.RequestExcel; +import com.pig4cloud.pigx.common.excel.annotation.ResponseExcel; import com.pig4cloud.pigx.common.log.annotation.SysLog; import io.swagger.annotations.Api; import lombok.AllArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; @@ -151,4 +155,27 @@ public class SysRoleController { return R.ok(sysRoleService.findRolesByRoleIds(roleIdList, CollUtil.join(roleIdList, StrUtil.UNDERLINE))); } + /** + * 导出excel 表格 + * @return + */ + @ResponseExcel + @GetMapping("/export") + @PreAuthorize("@pms.hasPermission('sys_role_export')") + public List export() { + return sysRoleService.listRole(); + } + + /** + * 导入角色 + * @param excelVOList 角色列表 + * @param bindingResult 错误信息列表 + * @return ok fail + */ + @PostMapping("/import") + @PreAuthorize("@pms.hasPermission('sys_role_export')") + public R importRole(@RequestExcel List excelVOList, BindingResult bindingResult) { + return sysRoleService.importRole(excelVOList, bindingResult); + } + } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysRoleService.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysRoleService.java index 16c26d60d..7f1055060 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysRoleService.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/SysRoleService.java @@ -21,7 +21,10 @@ package com.pig4cloud.pigx.admin.service; import com.baomidou.mybatisplus.extension.service.IService; import com.pig4cloud.pigx.admin.api.entity.SysRole; +import com.pig4cloud.pigx.admin.api.vo.RoleExcelVO; import com.pig4cloud.pigx.admin.api.vo.RoleVO; +import com.pig4cloud.pigx.common.core.util.R; +import org.springframework.validation.BindingResult; import java.util.List; @@ -64,4 +67,18 @@ public interface SysRoleService extends IService { */ Boolean updateRoleMenus(RoleVO roleVo); + /** + * 导入角色 + * @param excelVOList 角色列表 + * @param bindingResult 错误信息列表 + * @return ok fail + */ + R importRole(List excelVOList, BindingResult bindingResult); + + /** + * 查询全部的角色 + * @return list + */ + List listRole(); + } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleServiceImpl.java index abda10e42..a4af13179 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleServiceImpl.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysRoleServiceImpl.java @@ -19,21 +19,30 @@ package com.pig4cloud.pigx.admin.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.pig4cloud.pigx.admin.api.entity.SysRole; import com.pig4cloud.pigx.admin.api.entity.SysRoleMenu; +import com.pig4cloud.pigx.admin.api.vo.RoleExcelVO; import com.pig4cloud.pigx.admin.api.vo.RoleVO; import com.pig4cloud.pigx.admin.mapper.SysRoleMapper; import com.pig4cloud.pigx.admin.service.SysRoleMenuService; import com.pig4cloud.pigx.admin.service.SysRoleService; import com.pig4cloud.pigx.common.core.constant.CacheConstants; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.excel.vo.ErrorMessage; import lombok.AllArgsConstructor; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.BindingResult; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; /** *

@@ -94,4 +103,71 @@ public class SysRoleServiceImpl extends ServiceImpl impl return roleMenuService.saveRoleMenus(sysRole.getRoleCode(), roleVo.getRoleId(), roleVo.getMenuIds()); } + /** + * 导入角色 + * @param excelVOList 角色列表 + * @param bindingResult 错误信息列表 + * @return ok fail + */ + @Override + public R importRole(List excelVOList, BindingResult bindingResult) { + // 通用校验获取失败的数据 + List errorMessageList = (List) bindingResult.getTarget(); + + // 个性化校验逻辑 + List roleList = this.list(); + + // 执行数据插入操作 组装 RoleDto + for (int i = 0; i < excelVOList.size(); i++) { + RoleExcelVO excel = excelVOList.get(i); + Set errorMsg = new HashSet<>(); + // 检验角色名称或者角色编码是否存在 + boolean existRole = roleList.stream().anyMatch(sysRole -> excel.getRoleName().equals(sysRole.getRoleName()) + || excel.getRoleCode().equals(sysRole.getRoleCode())); + + if (existRole) { + errorMsg.add(String.format("%s %s 角色名或角色编码已经存在", excel.getRoleName(), excel.getRoleDesc())); + } + + // 数据合法情况 + if (CollUtil.isEmpty(errorMsg)) { + insertExcelRole(excel); + } + else { + // 数据不合法情况 + errorMessageList.add(new ErrorMessage((long) (i + 2), errorMsg)); + } + } + if (CollUtil.isNotEmpty(errorMessageList)) { + return R.failed(errorMessageList); + } + return R.ok(); + } + + /** + * 查询全部的角色 + * @return list + */ + @Override + public List listRole() { + List roleList = this.list(Wrappers.emptyWrapper()); + // 转换成execl 对象输出 + return roleList.stream().map(role -> { + RoleExcelVO roleExcelVO = new RoleExcelVO(); + BeanUtil.copyProperties(role, roleExcelVO); + return roleExcelVO; + }).collect(Collectors.toList()); + } + + /** + * 插入excel Role + */ + private void insertExcelRole(RoleExcelVO excel) { + SysRole sysRole = new SysRole(); + sysRole.setRoleName(excel.getRoleName()); + sysRole.setRoleDesc(excel.getRoleDesc()); + sysRole.setRoleCode(excel.getRoleCode()); + this.save(sysRole); + } + } diff --git a/pigx-upms/pigx-upms-biz/src/main/resources/file/role.xlsx b/pigx-upms/pigx-upms-biz/src/main/resources/file/role.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0c986e8bdee6e584a5648f86436797751f807516 GIT binary patch literal 8834 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 literal 0 HcmV?d00001