children = new ArrayList<>();
+
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/exception/ServiceException.java b/api-admin/src/main/java/com/glxp/api/admin/exception/ServiceException.java
new file mode 100644
index 00000000..98022d81
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/exception/ServiceException.java
@@ -0,0 +1,62 @@
+package com.glxp.api.admin.exception;
+
+/**
+ * 业务异常
+ */
+public final class ServiceException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 错误码
+ */
+ private Integer code;
+
+ /**
+ * 错误提示
+ */
+ private String message;
+
+ /**
+ * 错误明细,内部调试错误
+ *
+ */
+ private String detailMessage;
+
+ /**
+ * 空构造方法,避免反序列化问题
+ */
+ public ServiceException() {
+ }
+
+ public ServiceException(String message) {
+ this.message = message;
+ }
+
+ public ServiceException(String message, Integer code) {
+ this.message = message;
+ this.code = code;
+ }
+
+ public String getDetailMessage() {
+ return detailMessage;
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public ServiceException setMessage(String message) {
+ this.message = message;
+ return this;
+ }
+
+ public ServiceException setDetailMessage(String detailMessage) {
+ this.detailMessage = detailMessage;
+ return this;
+ }
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysDictDataRequest.java b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysDictDataRequest.java
new file mode 100644
index 00000000..63733f60
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysDictDataRequest.java
@@ -0,0 +1,14 @@
+package com.glxp.api.admin.req.auth;
+
+import com.glxp.api.admin.req.ListPageRequest;
+import lombok.Data;
+
+@Data
+public class SysDictDataRequest extends ListPageRequest {
+
+ private String dictType;
+ private String status;
+ private String dictLabel;
+ private String dictValue;
+
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysDictTypeRequest.java b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysDictTypeRequest.java
new file mode 100644
index 00000000..54158aca
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysDictTypeRequest.java
@@ -0,0 +1,16 @@
+package com.glxp.api.admin.req.auth;
+
+import com.glxp.api.admin.req.ListPageRequest;
+import lombok.Data;
+
+@Data
+public class SysDictTypeRequest extends ListPageRequest {
+
+ private Long dictId;
+
+ private String dictName;
+
+ private String dictType;
+
+ private String status;
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysMenuRequest.java b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysMenuRequest.java
new file mode 100644
index 00000000..794f471b
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysMenuRequest.java
@@ -0,0 +1,91 @@
+package com.glxp.api.admin.req.auth;
+
+import com.glxp.api.admin.req.ListPageRequest;
+import lombok.Data;
+
+@Data
+public class SysMenuRequest extends ListPageRequest {
+
+
+ private String parentName;
+
+ /**
+ * 父菜单ID
+ */
+ private Long parentId;
+
+
+ /**
+ * 菜单ID
+ */
+ private Long menuId;
+
+ /**
+ * 菜单名称
+ */
+ private String menuName;
+
+ /**
+ * 显示顺序
+ */
+ private Integer orderNum;
+
+ /**
+ * 路由地址
+ */
+ private String path;
+
+ /**
+ * 组件路径
+ */
+ private String component;
+
+ /**
+ * 路由参数
+ */
+ private String queryParam;
+
+ /**
+ * 是否为外链(0是 1否)
+ */
+ private String isFrame;
+
+ /**
+ * 是否缓存(0缓存 1不缓存)
+ */
+ private String isCache;
+
+ /**
+ * 类型(M目录 C菜单 F按钮)
+ */
+ private String menuType;
+
+ /**
+ * 显示状态(0显示 1隐藏)
+ */
+ private String visible;
+
+ /**
+ * 菜单状态(0正常 1停用)
+ */
+ private String status;
+
+ /**
+ * 权限字符串
+ */
+ private String perms;
+
+ /**
+ * 菜单图标
+ */
+ private String icon;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+
+ private String neMenuId;
+
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysRoleMenuRequest.java b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysRoleMenuRequest.java
new file mode 100644
index 00000000..16342e65
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysRoleMenuRequest.java
@@ -0,0 +1,19 @@
+package com.glxp.api.admin.req.auth;
+
+import com.glxp.api.admin.req.ListPageRequest;
+import lombok.Data;
+
+@Data
+public class SysRoleMenuRequest extends ListPageRequest {
+
+
+ /**
+ * 角色ID
+ */
+ private Long roleId;
+
+ /**
+ * 菜单ID
+ */
+ private Long menuId;
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysRoleRequest.java b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysRoleRequest.java
new file mode 100644
index 00000000..ca8a1727
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysRoleRequest.java
@@ -0,0 +1,18 @@
+package com.glxp.api.admin.req.auth;
+
+import com.glxp.api.admin.req.ListPageRequest;
+import lombok.Data;
+
+@Data
+public class SysRoleRequest extends ListPageRequest {
+
+ private Long roleId;
+ private String roleName;
+ private String roleKey;
+
+
+ private String neRoleName;
+ private String neRoleKey;
+ private Long neRoleId;
+
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysUserRoleRequest.java b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysUserRoleRequest.java
new file mode 100644
index 00000000..716cb515
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/req/auth/SysUserRoleRequest.java
@@ -0,0 +1,12 @@
+package com.glxp.api.admin.req.auth;
+
+import com.glxp.api.admin.req.ListPageRequest;
+import lombok.Data;
+
+@Data
+public class SysUserRoleRequest extends ListPageRequest {
+
+
+ private Long userId;
+ private Long roleId;
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/res/auth/LoginUserInfoResponse.java b/api-admin/src/main/java/com/glxp/api/admin/res/auth/LoginUserInfoResponse.java
index f6db2d61..e374cbc1 100644
--- a/api-admin/src/main/java/com/glxp/api/admin/res/auth/LoginUserInfoResponse.java
+++ b/api-admin/src/main/java/com/glxp/api/admin/res/auth/LoginUserInfoResponse.java
@@ -3,6 +3,7 @@ package com.glxp.api.admin.res.auth;
import lombok.Data;
import java.util.List;
+import java.util.Set;
/**
* 登录用户的信息视图
@@ -21,4 +22,11 @@ public class LoginUserInfoResponse {
private String locInvName;
private String locSubInvName;
+
+ Set roles; //用户角色
+ Set permissions; //用户权限
+
+
+ private String CustomerId;
+ private String companyName;
}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/AuthAdminService.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/AuthAdminService.java
index 1eca8494..7b6244f2 100644
--- a/api-admin/src/main/java/com/glxp/api/admin/service/auth/AuthAdminService.java
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/AuthAdminService.java
@@ -30,4 +30,13 @@ public interface AuthAdminService {
* @return
*/
List getHospitalUserList();
+
+
+ List selectAllocatedList(AuthAdminQueryRequest authAdminQueryRequest);
+
+
+ List selectUnallocatedList(AuthAdminQueryRequest authAdminQueryRequest);
+
+
+ void insertUserAuth(Long userId, List roleIds);
}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysDictDataService.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysDictDataService.java
new file mode 100644
index 00000000..1a918e67
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysDictDataService.java
@@ -0,0 +1,62 @@
+package com.glxp.api.admin.service.auth;
+
+
+import com.glxp.api.admin.entity.auth.SysDictData;
+import com.glxp.api.admin.req.auth.SysDictDataRequest;
+
+import java.util.List;
+
+/**
+ * 字典 业务层
+ */
+public interface ISysDictDataService {
+
+
+ /**
+ * 根据条件分页查询字典数据
+ *
+ * @param dictData 字典数据信息
+ * @return 字典数据集合信息
+ */
+ List selectDictDataList(SysDictDataRequest sysDictDataRequest);
+
+ /**
+ * 根据字典类型和字典键值查询字典数据信息
+ *
+ * @param dictType 字典类型
+ * @param dictValue 字典键值
+ * @return 字典标签
+ */
+ String selectDictLabel(String dictType, String dictValue);
+
+ /**
+ * 根据字典数据ID查询信息
+ *
+ * @param dictCode 字典数据ID
+ * @return 字典数据
+ */
+ SysDictData selectDictDataById(Long dictCode);
+
+ /**
+ * 批量删除字典数据信息
+ *
+ * @param dictCodes 需要删除的字典数据ID
+ */
+ void deleteDictDataByIds(Long[] dictCodes);
+
+ /**
+ * 新增保存字典数据信息
+ *
+ * @param dictData 字典数据信息
+ * @return 结果
+ */
+ List insertDictData(SysDictData dictData);
+
+ /**
+ * 修改保存字典数据信息
+ *
+ * @param dictData 字典数据信息
+ * @return 结果
+ */
+ List updateDictData(SysDictData dictData);
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysDictTypeService.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysDictTypeService.java
new file mode 100644
index 00000000..a9cc2afc
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysDictTypeService.java
@@ -0,0 +1,97 @@
+package com.glxp.api.admin.service.auth;
+
+
+import com.glxp.api.admin.entity.auth.SysDictData;
+import com.glxp.api.admin.entity.auth.SysDictType;
+import com.glxp.api.admin.req.auth.SysDictTypeRequest;
+
+import java.util.List;
+
+/**
+ * 字典 业务层
+ */
+public interface ISysDictTypeService {
+
+
+ List selectDictTypeList(SysDictTypeRequest sysDictTypeRequest);
+
+ /**
+ * 根据所有字典类型
+ *
+ * @return 字典类型集合信息
+ */
+ List selectDictTypeAll();
+
+ /**
+ * 根据字典类型查询字典数据
+ *
+ * @param dictType 字典类型
+ * @return 字典数据集合信息
+ */
+ List selectDictDataByType(String dictType);
+
+ /**
+ * 根据字典类型ID查询信息
+ *
+ * @param dictId 字典类型ID
+ * @return 字典类型
+ */
+ SysDictType selectDictTypeById(Long dictId);
+
+ /**
+ * 根据字典类型查询信息
+ *
+ * @param dictType 字典类型
+ * @return 字典类型
+ */
+ SysDictType selectDictTypeByType(String dictType);
+
+ /**
+ * 批量删除字典信息
+ *
+ * @param dictIds 需要删除的字典ID
+ */
+ void deleteDictTypeByIds(Long[] dictIds);
+
+ /**
+ * 重置字典缓存数据
+ */
+ void resetDictCache();
+
+ /**
+ * 新增保存字典类型信息
+ *
+ * @param dictType 字典类型信息
+ * @return 结果
+ */
+ List insertDictType(SysDictType dictType);
+
+ /**
+ * 修改保存字典类型信息
+ *
+ * @param dictType 字典类型信息
+ * @return 结果
+ */
+ List updateDictType(SysDictType dictType);
+
+ /**
+ * 校验字典类型称是否唯一
+ *
+ * @param dictType 字典类型
+ * @return 结果
+ */
+ String checkDictTypeUnique(SysDictType dictType);
+
+
+ String getDictLabel(String dictType, String dictValue, String separator);
+
+ /**
+ * 根据字典类型和字典标签获取字典值
+ *
+ * @param dictType 字典类型
+ * @param dictLabel 字典标签
+ * @param separator 分隔符
+ * @return 字典值
+ */
+ String getDictValue(String dictType, String dictLabel, String separator);
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysMenuService.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysMenuService.java
new file mode 100644
index 00000000..0b2e50ab
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysMenuService.java
@@ -0,0 +1,132 @@
+package com.glxp.api.admin.service.auth;
+
+import cn.hutool.core.lang.tree.Tree;
+import com.glxp.api.admin.entity.auth.RouterEntity;
+import com.glxp.api.admin.entity.auth.SysMenu;
+
+import java.util.List;
+import java.util.Set;
+
+public interface ISysMenuService {
+
+ /**
+ * 根据用户查询系统菜单列表
+ *
+ * @param userId 用户ID
+ * @return 菜单列表
+ */
+ List selectMenuList(Long userId);
+
+ /**
+ * 根据用户查询系统菜单列表
+ *
+ * @param menu 菜单信息
+ * @param userId 用户ID
+ * @return 菜单列表
+ */
+ List selectMenuList(SysMenu menu, Long userId);
+
+ /**
+ * 根据用户ID查询权限
+ *
+ * @param userId 用户ID
+ * @return 权限列表
+ */
+ Set selectMenuPermsByUserId(Long userId);
+
+ /**
+ * 根据角色ID查询权限
+ *
+ * @param roleId 角色ID
+ * @return 权限列表
+ */
+ Set selectMenuPermsByRoleId(Long roleId);
+
+ /**
+ * 根据用户ID查询菜单树信息
+ *
+ * @param userId 用户ID
+ * @return 菜单列表
+ */
+ List selectMenuTreeByUserId(Long userId);
+
+ /**
+ * 根据角色ID查询菜单树信息
+ *
+ * @param roleId 角色ID
+ * @return 选中菜单列表
+ */
+ List selectMenuListByRoleId(Long roleId);
+
+ /**
+ * 构建前端路由所需要的菜单
+ *
+ * @param menus 菜单列表
+ * @return 路由列表
+ */
+ List buildMenus(List menus);
+
+ /**
+ * 构建前端所需要下拉树结构
+ *
+ * @param menus 菜单列表
+ * @return 下拉树结构列表
+ */
+ List> buildMenuTreeSelect(List menus);
+
+ /**
+ * 根据菜单ID查询信息
+ *
+ * @param menuId 菜单ID
+ * @return 菜单信息
+ */
+ SysMenu selectMenuById(Long menuId);
+
+ /**
+ * 是否存在菜单子节点
+ *
+ * @param menuId 菜单ID
+ * @return 结果 true 存在 false 不存在
+ */
+ boolean hasChildByMenuId(Long menuId);
+
+ /**
+ * 查询菜单是否存在角色
+ *
+ * @param menuId 菜单ID
+ * @return 结果 true 存在 false 不存在
+ */
+ boolean checkMenuExistRole(Long menuId);
+
+ /**
+ * 新增保存菜单信息
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ int insertMenu(SysMenu menu);
+
+ /**
+ * 修改保存菜单信息
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ int updateMenu(SysMenu menu);
+
+ /**
+ * 删除菜单管理信息
+ *
+ * @param menuId 菜单ID
+ * @return 结果
+ */
+ int deleteMenuById(Long menuId);
+
+ /**
+ * 校验菜单名称是否唯一
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ String checkMenuNameUnique(SysMenu menu);
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysRoleService.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysRoleService.java
new file mode 100644
index 00000000..1bf598a9
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/ISysRoleService.java
@@ -0,0 +1,176 @@
+package com.glxp.api.admin.service.auth;
+
+
+import com.glxp.api.admin.entity.auth.SysRole;
+import com.glxp.api.admin.entity.auth.SysUserRole;
+import com.glxp.api.admin.req.auth.SysRoleRequest;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 角色业务层
+ */
+public interface ISysRoleService {
+
+
+ List selectPageRoleList(SysRoleRequest sysRoleRequest);
+
+ /**
+ * 根据条件分页查询角色数据
+ *
+ * @return 角色数据集合信息
+ */
+ List selectRoleList(SysRoleRequest sysRoleRequest);
+
+ /**
+ * 根据用户ID查询角色列表
+ *
+ * @param userId 用户ID
+ * @return 角色列表
+ */
+ List selectRolesByUserId(Long userId);
+
+ /**
+ * 根据用户ID查询角色权限
+ *
+ * @param userId 用户ID
+ * @return 权限列表
+ */
+ Set selectRolePermissionByUserId(Long userId);
+
+ /**
+ * 查询所有角色
+ *
+ * @return 角色列表
+ */
+ List selectRoleAll();
+
+ /**
+ * 根据用户ID获取角色选择框列表
+ *
+ * @param userId 用户ID
+ * @return 选中角色ID列表
+ */
+ List selectRoleListByUserId(Long userId);
+
+ /**
+ * 通过角色ID查询角色
+ *
+ * @param roleId 角色ID
+ * @return 角色对象信息
+ */
+ SysRole selectRoleById(Long roleId);
+
+ /**
+ * 校验角色名称是否唯一
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ String checkRoleNameUnique(SysRole role);
+
+ /**
+ * 校验角色权限是否唯一
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ String checkRoleKeyUnique(SysRole role);
+
+ /**
+ * 校验角色是否允许操作
+ *
+ * @param role 角色信息
+ */
+ void checkRoleAllowed(SysRole role);
+
+ /**
+ * 校验角色是否有数据权限
+ *
+ * @param roleId 角色id
+ */
+ void checkRoleDataScope(Long roleId);
+
+ /**
+ * 通过角色ID查询角色使用数量
+ *
+ * @param roleId 角色ID
+ * @return 结果
+ */
+ long countUserRoleByRoleId(Long roleId);
+
+ /**
+ * 新增保存角色信息
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ int insertRole(SysRole role);
+
+ /**
+ * 修改保存角色信息
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ int updateRole(SysRole role);
+
+ /**
+ * 修改角色状态
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ int updateRoleStatus(SysRole role);
+
+ /**
+ * 修改数据权限信息
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ int authDataScope(SysRole role);
+
+ /**
+ * 通过角色ID删除角色
+ *
+ * @param roleId 角色ID
+ * @return 结果
+ */
+ int deleteRoleById(Long roleId);
+
+ /**
+ * 批量删除角色信息
+ *
+ * @param roleIds 需要删除的角色ID
+ * @return 结果
+ */
+ int deleteRoleByIds(Long[] roleIds);
+
+ /**
+ * 取消授权用户角色
+ *
+ * @param userRole 用户和角色关联信息
+ * @return 结果
+ */
+ int deleteAuthUser(SysUserRole userRole);
+
+ /**
+ * 批量取消授权用户角色
+ *
+ * @param roleId 角色ID
+ * @param userIds 需要取消授权的用户数据ID
+ * @return 结果
+ */
+ int deleteAuthUsers(Long roleId, Long[] userIds);
+
+ /**
+ * 批量选择授权用户角色
+ *
+ * @param roleId 角色ID
+ * @param userIds 需要删除的用户数据ID
+ * @return 结果
+ */
+ int insertAuthUsers(Long roleId, Long[] userIds);
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/SysPermissionService.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/SysPermissionService.java
new file mode 100644
index 00000000..b0f130d7
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/SysPermissionService.java
@@ -0,0 +1,62 @@
+package com.glxp.api.admin.service.auth;
+
+import com.glxp.api.admin.entity.auth.AuthAdmin;
+import com.glxp.api.admin.entity.auth.SysRole;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@RequiredArgsConstructor
+@Service
+public class SysPermissionService {
+
+ private final ISysRoleService roleService;
+ private final ISysMenuService menuService;
+
+ /**
+ * 获取角色数据权限
+ *
+ * @param user 用户信息
+ * @return 角色权限信息
+ */
+ public Set getRolePermission(AuthAdmin user) {
+ Set roles = new HashSet();
+ // 管理员拥有所有权限
+ if (user.isAdmin()) {
+ roles.add("admin");
+ } else {
+ roles.addAll(roleService.selectRolePermissionByUserId(user.getId()));
+ }
+ return roles;
+ }
+
+ /**
+ * 获取菜单数据权限
+ *
+ * @param user 用户信息
+ * @return 菜单权限信息
+ */
+ public Set getMenuPermission(AuthAdmin user) {
+ Set perms = new HashSet();
+ // 管理员拥有所有权限
+ if (user.isAdmin()) {
+ perms.add("*:*:*");
+ } else {
+ List roles = user.getRoles();
+ if (!roles.isEmpty() && roles.size() > 1) {
+ // 多角色设置permissions属性,以便数据权限匹配权限
+ for (SysRole role : roles) {
+ Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
+ role.setPermissions(rolePerms);
+ perms.addAll(rolePerms);
+ }
+ } else {
+ perms.addAll(menuService.selectMenuPermsByUserId(user.getId()));
+ }
+ }
+ return perms;
+ }
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/AuthAdminServiceImpl.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/AuthAdminServiceImpl.java
index 464d2d57..8d705935 100644
--- a/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/AuthAdminServiceImpl.java
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/AuthAdminServiceImpl.java
@@ -1,15 +1,20 @@
package com.glxp.api.admin.service.auth.impl;
+import cn.hutool.core.util.ArrayUtil;
import com.github.pagehelper.PageHelper;
import com.glxp.api.admin.dao.auth.AuthAdminDao;
+import com.glxp.api.admin.dao.auth.SysUserRoleMapper;
import com.glxp.api.admin.entity.auth.AuthAdmin;
+import com.glxp.api.admin.entity.auth.SysUserRole;
import com.glxp.api.admin.exception.JsonException;
import com.glxp.api.admin.req.auth.AuthAdminQueryRequest;
+import com.glxp.api.admin.req.auth.SysUserRoleRequest;
import com.glxp.api.admin.service.auth.AuthAdminService;
import com.glxp.api.common.enums.ResultEnum;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -19,6 +24,8 @@ public class AuthAdminServiceImpl implements AuthAdminService {
@Resource
private AuthAdminDao authAdminDao;
+ @Resource
+ SysUserRoleMapper sysUserRoleMapper;
@Override
public List listAdminPage(AuthAdminQueryRequest authAdminQueryRequest) {
@@ -120,4 +127,39 @@ public class AuthAdminServiceImpl implements AuthAdminService {
return authAdminDao.selectHospitalUser();
}
+
+ @Override
+ public List selectAllocatedList(AuthAdminQueryRequest authAdminQueryRequest) {
+ return authAdminDao.selectAllocatedList(authAdminQueryRequest);
+ }
+
+ @Override
+ public List selectUnallocatedList(AuthAdminQueryRequest authAdminQueryRequest) {
+ return authAdminDao.selectUnallocatedList(authAdminQueryRequest);
+ }
+
+ @Override
+ public void insertUserAuth(Long userId, List roleIds) {
+
+ SysUserRoleRequest sysUserRoleRequest = new SysUserRoleRequest();
+ sysUserRoleRequest.setUserId(userId);
+ sysUserRoleMapper.delete(sysUserRoleRequest);
+ insertUserRole(userId, roleIds);
+ }
+
+
+ public void insertUserRole(Long userId, List roleIds) {
+ if (ArrayUtil.isNotEmpty(roleIds)) {
+ // 新增用户与角色管理
+ List list = new ArrayList<>(roleIds.size());
+ for (Long roleId : roleIds) {
+ SysUserRole ur = new SysUserRole();
+ ur.setUserId(userId);
+ ur.setRoleId(roleId);
+ list.add(ur);
+ }
+ sysUserRoleMapper.insertBatch(list);
+ }
+ }
+
}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysDictDataServiceImpl.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysDictDataServiceImpl.java
new file mode 100644
index 00000000..7ce75989
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysDictDataServiceImpl.java
@@ -0,0 +1,84 @@
+package com.glxp.api.admin.service.auth.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.github.pagehelper.PageHelper;
+import com.glxp.api.admin.dao.auth.SysDictDataMapper;
+import com.glxp.api.admin.entity.auth.SysDictData;
+import com.glxp.api.admin.exception.ServiceException;
+import com.glxp.api.admin.req.auth.SysDictDataRequest;
+import com.glxp.api.admin.service.auth.ISysDictDataService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 字典 业务层处理
+ */
+@Service
+public class SysDictDataServiceImpl implements ISysDictDataService {
+ @Resource
+ SysDictDataMapper baseMapper;
+
+
+ @Override
+ public List selectDictDataList(SysDictDataRequest sysDictDataRequest) {
+
+ if (sysDictDataRequest.getPage() != null) {
+ int offset = (sysDictDataRequest.getPage() - 1) * sysDictDataRequest.getLimit();
+ PageHelper.offsetPage(offset, sysDictDataRequest.getLimit());
+ }
+
+ return baseMapper.selectDictDataList(sysDictDataRequest);
+
+ }
+
+ @Override
+ public String selectDictLabel(String dictType, String dictValue) {
+
+ SysDictDataRequest sysDictDataRequest = new SysDictDataRequest();
+ sysDictDataRequest.setDictType(dictType);
+ sysDictDataRequest.setDictValue(dictValue);
+ List dictData = baseMapper.selectDictDataList(sysDictDataRequest);
+ if (CollUtil.isNotEmpty(dictData))
+ return dictData.get(0).getDictLabel();
+ else
+ return null;
+ }
+
+ @Override
+ public SysDictData selectDictDataById(Long dictCode) {
+ return baseMapper.selectById(dictCode);
+ }
+
+ @Override
+ public void deleteDictDataByIds(Long[] dictCodes) {
+ for (Long dictCode : dictCodes) {
+ SysDictData data = selectDictDataById(dictCode);
+ baseMapper.deleteById(dictCode);
+ }
+ }
+
+ @Override
+ public List insertDictData(SysDictData data) {
+ int row = baseMapper.insert(data);
+ if (row > 0) {
+ SysDictDataRequest sysDictDataRequest = new SysDictDataRequest();
+ sysDictDataRequest.setDictType(data.getDictType());
+ return baseMapper.selectDictDataList(sysDictDataRequest);
+ }
+ throw new ServiceException("操作失败");
+ }
+
+ @Override
+ public List updateDictData(SysDictData data) {
+ int row = baseMapper.updateById(data);
+ if (row > 0) {
+ SysDictDataRequest sysDictDataRequest = new SysDictDataRequest();
+ sysDictDataRequest.setDictType(data.getDictType());
+ return baseMapper.selectDictDataList(sysDictDataRequest);
+ }
+ throw new ServiceException("操作失败");
+ }
+
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysDictTypeServiceImpl.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysDictTypeServiceImpl.java
new file mode 100644
index 00000000..e45f9392
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysDictTypeServiceImpl.java
@@ -0,0 +1,239 @@
+package com.glxp.api.admin.service.auth.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.github.pagehelper.PageHelper;
+import com.glxp.api.admin.constant.Constant;
+import com.glxp.api.admin.dao.auth.SysDictDataMapper;
+import com.glxp.api.admin.dao.auth.SysDictTypeMapper;
+import com.glxp.api.admin.entity.auth.SysDictData;
+import com.glxp.api.admin.entity.auth.SysDictType;
+import com.glxp.api.admin.exception.ServiceException;
+import com.glxp.api.admin.req.auth.SysDictDataRequest;
+import com.glxp.api.admin.req.auth.SysDictTypeRequest;
+import com.glxp.api.admin.service.auth.ISysDictTypeService;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 字典 业务层处理
+ */
+@RequiredArgsConstructor
+@Service
+public class SysDictTypeServiceImpl implements ISysDictTypeService {
+
+ private final SysDictTypeMapper baseMapper;
+ private final SysDictDataMapper dictDataMapper;
+
+ @Override
+ public List selectDictTypeList(SysDictTypeRequest sysDictTypeRequest) {
+ if (sysDictTypeRequest.getPage() != null) {
+ int offset = (sysDictTypeRequest.getPage() - 1) * sysDictTypeRequest.getLimit();
+ PageHelper.offsetPage(offset, sysDictTypeRequest.getLimit());
+ }
+ return baseMapper.selectDictTypeList(sysDictTypeRequest);
+ }
+
+ @Override
+ public List selectDictTypeAll() {
+ return baseMapper.selectDictTypeList(new SysDictTypeRequest());
+ }
+
+ /**
+ * 根据字典类型查询字典数据
+ *
+ * @param dictType 字典类型
+ * @return 字典数据集合信息
+ */
+ @Override
+ public List selectDictDataByType(String dictType) {
+ SysDictDataRequest sysDictTypeRequest = new SysDictDataRequest();
+ sysDictTypeRequest.setDictType(dictType);
+ List dictDatas = dictDataMapper.selectDictDataList(sysDictTypeRequest);
+ if (CollUtil.isNotEmpty(dictDatas)) {
+ return dictDatas;
+ }
+ return null;
+ }
+
+ /**
+ * 根据字典类型ID查询信息
+ *
+ * @param dictId 字典类型ID
+ * @return 字典类型
+ */
+ @Override
+ public SysDictType selectDictTypeById(Long dictId) {
+ return baseMapper.selectById(dictId);
+ }
+
+ /**
+ * 根据字典类型查询信息
+ *
+ * @param dictType 字典类型
+ * @return 字典类型
+ */
+ @Override
+ public SysDictType selectDictTypeByType(String dictType) {
+ SysDictTypeRequest sysDictTypeRequest = new SysDictTypeRequest();
+ sysDictTypeRequest.setDictType(dictType);
+ List sysDictTypes = baseMapper.selectDictTypeList(sysDictTypeRequest);
+ if (CollUtil.isNotEmpty(sysDictTypes)) {
+ return sysDictTypes.get(0);
+ } else
+ return null;
+ }
+
+ /**
+ * 批量删除字典类型信息
+ *
+ * @param dictIds 需要删除的字典ID
+ */
+ @Override
+ public void deleteDictTypeByIds(Long[] dictIds) {
+ for (Long dictId : dictIds) {
+ SysDictType dictType = selectDictTypeById(dictId);
+
+ SysDictDataRequest sysDictDataRequest = new SysDictDataRequest();
+ sysDictDataRequest.setDictType(dictType.getDictType());
+ SysDictData sysDictData = dictDataMapper.exists(sysDictDataRequest);
+
+ if (sysDictData != null) {
+ throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
+ }
+ }
+ baseMapper.deleteBatchIds(Arrays.asList(dictIds));
+ }
+
+ /**
+ * 重置字典缓存数据
+ */
+ @Override
+ public void resetDictCache() {
+ }
+
+ /**
+ * 新增保存字典类型信息
+ *
+ * @param dict 字典类型信息
+ * @return 结果
+ */
+ @Override
+ public List insertDictType(SysDictType dict) {
+ int row = baseMapper.insert(dict);
+ if (row > 0) {
+ return new ArrayList<>();
+ }
+ throw new ServiceException("操作失败");
+ }
+
+ /**
+ * 修改保存字典类型信息
+ *
+ * @param dict 字典类型信息
+ * @return 结果
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public List updateDictType(SysDictType dict) {
+ SysDictType oldDict = baseMapper.selectById(dict.getDictId());
+// dictDataMapper.updateByType(null, new LambdaUpdateWrapper()
+// .set(SysDictData::getDictType, dict.getDictType())
+// .eq(SysDictData::getDictType, oldDict.getDictType()));
+ int row = baseMapper.updateById(dict);
+ if (row > 0) {
+ SysDictDataRequest sysDictDataRequest = new SysDictDataRequest();
+ sysDictDataRequest.setDictType(dict.getDictType());
+ return dictDataMapper.selectDictDataList(sysDictDataRequest);
+ }
+ throw new ServiceException("操作失败");
+ }
+
+ /**
+ * 校验字典类型称是否唯一
+ *
+ * @param dict 字典类型
+ * @return 结果
+ */
+ @Override
+ public String checkDictTypeUnique(SysDictType dict) {
+
+ SysDictTypeRequest sysDictTypeRequest = new SysDictTypeRequest();
+ sysDictTypeRequest.setDictType(dict.getDictType());
+ SysDictType exist = baseMapper.exists(sysDictTypeRequest);
+ if (exist == null) {
+ return Constant.NOT_UNIQUE;
+ }
+ return Constant.UNIQUE;
+ }
+
+ /**
+ * 根据字典类型和字典值获取字典标签
+ *
+ * @param dictType 字典类型
+ * @param dictValue 字典值
+ * @param separator 分隔符
+ * @return 字典标签
+ */
+ @Override
+ public String getDictLabel(String dictType, String dictValue, String separator) {
+ StringBuilder propertyString = new StringBuilder();
+ List datas = selectDictDataByType(dictType);
+
+ if (StringUtils.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas)) {
+ for (SysDictData dict : datas) {
+ for (String value : dictValue.split(separator)) {
+ if (value.equals(dict.getDictValue())) {
+ propertyString.append(dict.getDictLabel() + separator);
+ break;
+ }
+ }
+ }
+ } else {
+ for (SysDictData dict : datas) {
+ if (dictValue.equals(dict.getDictValue())) {
+ return dict.getDictLabel();
+ }
+ }
+ }
+ return StringUtils.stripEnd(propertyString.toString(), separator);
+ }
+
+ /**
+ * 根据字典类型和字典标签获取字典值
+ *
+ * @param dictType 字典类型
+ * @param dictLabel 字典标签
+ * @param separator 分隔符
+ * @return 字典值
+ */
+ @Override
+ public String getDictValue(String dictType, String dictLabel, String separator) {
+ StringBuilder propertyString = new StringBuilder();
+ List datas = selectDictDataByType(dictType);
+
+ if (StringUtils.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas)) {
+ for (SysDictData dict : datas) {
+ for (String label : dictLabel.split(separator)) {
+ if (label.equals(dict.getDictLabel())) {
+ propertyString.append(dict.getDictValue() + separator);
+ break;
+ }
+ }
+ }
+ } else {
+ for (SysDictData dict : datas) {
+ if (dictLabel.equals(dict.getDictLabel())) {
+ return dict.getDictValue();
+ }
+ }
+ }
+ return StringUtils.stripEnd(propertyString.toString(), separator);
+ }
+
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysMenuServiceImpl.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysMenuServiceImpl.java
new file mode 100644
index 00000000..c21ea75b
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysMenuServiceImpl.java
@@ -0,0 +1,460 @@
+package com.glxp.api.admin.service.auth.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.http.HttpUtil;
+import com.glxp.api.admin.constant.Constant;
+import com.glxp.api.admin.dao.auth.SysMenuDao;
+import com.glxp.api.admin.dao.auth.SysRoleMapper;
+import com.glxp.api.admin.dao.auth.SysRoleMenuMapper;
+import com.glxp.api.admin.entity.auth.*;
+import com.glxp.api.admin.req.auth.SysMenuRequest;
+import com.glxp.api.admin.req.auth.SysRoleMenuRequest;
+import com.glxp.api.admin.service.auth.ISysMenuService;
+import com.glxp.api.admin.util.TreeBuildUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * 菜单 业务层处理
+ */
+@Service
+public class SysMenuServiceImpl implements ISysMenuService {
+
+
+ @Resource
+ SysMenuDao sysMenuDao;
+ @Resource
+ SysRoleMapper sysRoleMapper;
+ @Resource
+ SysRoleMenuMapper sysRoleMenuMapper;
+
+ /**
+ * 根据用户查询系统菜单列表
+ *
+ * @param userId 用户ID
+ * @return 菜单列表
+ */
+ @Override
+ public List selectMenuList(Long userId) {
+ return selectMenuList(new SysMenu(), userId);
+ }
+
+ /**
+ * 查询系统菜单列表
+ *
+ * @param menu 菜单信息
+ * @return 菜单列表
+ */
+ @Override
+ public List selectMenuList(SysMenu menu, Long userId) {
+ List menuList = null;
+ // 管理员显示所有菜单信息
+ SysMenuRequest sysMenuRequest = new SysMenuRequest();
+ BeanUtils.copyProperties(menu, sysMenuRequest);
+ if (Constant.ADMIN_ID.equals(userId + "")) {
+ menuList = sysMenuDao.selectMenuList(sysMenuRequest);
+ } else {
+ menuList = sysMenuDao.selectMenuListByUserId(sysMenuRequest);
+ }
+ return menuList;
+ }
+
+ /**
+ * 根据用户ID查询权限
+ *
+ * @param userId 用户ID
+ * @return 权限列表
+ */
+ @Override
+ public Set selectMenuPermsByUserId(Long userId) {
+ List perms = sysMenuDao.selectMenuPermsByUserId(userId);
+ Set permsSet = new HashSet<>();
+ for (String perm : perms) {
+ if (StringUtils.isNotEmpty(perm)) {
+ permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+ }
+ }
+ return permsSet;
+ }
+
+ /**
+ * 根据角色ID查询权限
+ *
+ * @param roleId 角色ID
+ * @return 权限列表
+ */
+ @Override
+ public Set selectMenuPermsByRoleId(Long roleId) {
+ List perms = sysMenuDao.selectMenuPermsByRoleId(roleId);
+ Set permsSet = new HashSet<>();
+ for (String perm : perms) {
+ if (StringUtils.isNotEmpty(perm)) {
+ permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+ }
+ }
+ return permsSet;
+ }
+
+ /**
+ * 根据用户ID查询菜单
+ *
+ * @param userId 用户名称
+ * @return 菜单列表
+ */
+ @Override
+ public List selectMenuTreeByUserId(Long userId) {
+ List menus = null;
+ if (Constant.ADMIN_ID.equals(userId + "")) {
+ menus = sysMenuDao.selectMenuTreeAll();
+ } else {
+ menus = sysMenuDao.selectMenuTreeByUserId(userId);
+ }
+ return getChildPerms(menus, 0);
+ }
+
+ /**
+ * 根据角色ID查询菜单树信息
+ *
+ * @param roleId 角色ID
+ * @return 选中菜单列表
+ */
+ @Override
+ public List selectMenuListByRoleId(Long roleId) {
+ SysRole role = sysRoleMapper.selectById(roleId);
+ return sysMenuDao.selectMenuListByRoleId(roleId, role.getMenuCheckStrictly());
+ }
+
+ /**
+ * 构建前端路由所需要的菜单
+ *
+ * @param menus 菜单列表
+ * @return 路由列表
+ */
+ @Override
+ public List buildMenus(List menus) {
+ List routers = new LinkedList();
+ for (SysMenu menu : menus) {
+ RouterEntity router = new RouterEntity();
+ router.setHidden("1".equals(menu.getVisible()));
+ router.setName(getRouteName(menu));
+ router.setPath(getRouterPath(menu));
+ router.setComponent(getComponent(menu));
+ router.setQuery(menu.getQueryParam());
+ router.setMeta(new MetaEntity(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
+ List cMenus = menu.getChildren();
+ if (!cMenus.isEmpty() && Constant.TYPE_DIR.equals(menu.getMenuType())) {
+ router.setAlwaysShow(true);
+ router.setRedirect("noRedirect");
+ router.setChildren(buildMenus(cMenus));
+ } else if (isMenuFrame(menu)) {
+ router.setMeta(null);
+ List childrenList = new ArrayList();
+ RouterEntity children = new RouterEntity();
+ children.setPath(menu.getPath());
+ children.setComponent(menu.getComponent());
+ children.setName(StringUtils.capitalize(menu.getPath()));
+ children.setMeta(new MetaEntity(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
+ children.setQuery(menu.getQueryParam());
+ childrenList.add(children);
+ router.setChildren(childrenList);
+ } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
+ router.setMeta(new MetaEntity(menu.getMenuName(), menu.getIcon()));
+ router.setPath("/");
+ List childrenList = new ArrayList();
+ RouterEntity children = new RouterEntity();
+ String routerPath = innerLinkReplaceEach(menu.getPath());
+ children.setPath(routerPath);
+ children.setComponent(Constant.INNER_LINK);
+ children.setName(StringUtils.capitalize(routerPath));
+ children.setMeta(new MetaEntity(menu.getMenuName(), menu.getIcon(), menu.getPath()));
+ childrenList.add(children);
+ router.setChildren(childrenList);
+ }
+ routers.add(router);
+ }
+ return routers;
+ }
+
+ /**
+ * 构建前端所需要下拉树结构
+ *
+ * @param menus 菜单列表
+ * @return 下拉树结构列表
+ */
+ @Override
+ public List> buildMenuTreeSelect(List menus) {
+ if (CollUtil.isEmpty(menus)) {
+ return CollUtil.newArrayList();
+ }
+ return TreeBuildUtils.build(menus, (menu, tree) ->
+ tree.setId(menu.getMenuId())
+ .setParentId(menu.getParentId())
+ .setName(menu.getMenuName())
+ .setWeight(menu.getOrderNum()));
+ }
+
+ /**
+ * 根据菜单ID查询信息
+ *
+ * @param menuId 菜单ID
+ * @return 菜单信息
+ */
+ @Override
+ public SysMenu selectMenuById(Long menuId) {
+ return sysMenuDao.selectById(menuId);
+ }
+
+ /**
+ * 是否存在菜单子节点
+ *
+ * @param menuId 菜单ID
+ * @return 结果
+ */
+ @Override
+ public boolean hasChildByMenuId(Long menuId) {
+
+
+ SysMenuRequest sysMenuRequest = new SysMenuRequest();
+ sysMenuRequest.setParentId(menuId);
+ List menuList = sysMenuDao.selectMenuList(sysMenuRequest);
+
+
+ if (CollUtil.isEmpty(menuList)) {
+ return false;
+ } else
+ return true;
+
+ }
+
+ /**
+ * 查询菜单使用数量
+ *
+ * @param menuId 菜单ID
+ * @return 结果
+ */
+ @Override
+ public boolean checkMenuExistRole(Long menuId) {
+
+
+ SysRoleMenuRequest sysRoleRequest = new SysRoleMenuRequest();
+ sysRoleRequest.setMenuId(menuId);
+ List sysRoleMenus = sysRoleMenuMapper.selectRoleMenuList(sysRoleRequest);
+ if (CollUtil.isEmpty(sysRoleMenus)) {
+ return false;
+ }
+ return true;
+
+ }
+
+ /**
+ * 新增保存菜单信息
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ @Override
+ public int insertMenu(SysMenu menu) {
+ return sysMenuDao.insert(menu);
+ }
+
+ /**
+ * 修改保存菜单信息
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ @Override
+ public int updateMenu(SysMenu menu) {
+ return sysMenuDao.updateById(menu);
+ }
+
+ /**
+ * 删除菜单管理信息
+ *
+ * @param menuId 菜单ID
+ * @return 结果
+ */
+ @Override
+ public int deleteMenuById(Long menuId) {
+ return sysMenuDao.deleteById(menuId);
+ }
+
+ /**
+ * 校验菜单名称是否唯一
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ @Override
+ public String checkMenuNameUnique(SysMenu menu) {
+
+
+ SysMenuRequest sysMenuRequest = new SysMenuRequest();
+ sysMenuRequest.setParentId(menu.getParentId());
+ sysMenuRequest.setMenuName(menu.getMenuName());
+ List menuList = sysMenuDao.selectMenuList(sysMenuRequest);
+ if (CollUtil.isEmpty(menuList)) {
+ return Constant.UNIQUE;
+ } else
+ return Constant.NOT_UNIQUE;
+ }
+
+ /**
+ * 获取路由名称
+ *
+ * @param menu 菜单信息
+ * @return 路由名称
+ */
+ public String getRouteName(SysMenu menu) {
+ String routerName = StringUtils.capitalize(menu.getPath());
+ // 非外链并且是一级目录(类型为目录)
+ if (isMenuFrame(menu)) {
+ routerName = StringUtils.EMPTY;
+ }
+ return routerName;
+ }
+
+ /**
+ * 获取路由地址
+ *
+ * @param menu 菜单信息
+ * @return 路由地址
+ */
+ public String getRouterPath(SysMenu menu) {
+ String routerPath = menu.getPath();
+ // 内链打开外网方式
+ if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
+ routerPath = innerLinkReplaceEach(routerPath);
+ }
+ // 非外链并且是一级目录(类型为目录)
+ if (0 == menu.getParentId().intValue() && Constant.TYPE_DIR.equals(menu.getMenuType())
+ && Constant.NO_FRAME.equals(menu.getIsFrame())) {
+ routerPath = "/" + menu.getPath();
+ }
+ // 非外链并且是一级目录(类型为菜单)
+ else if (isMenuFrame(menu)) {
+ routerPath = "/";
+ }
+ return routerPath;
+ }
+
+ /**
+ * 获取组件信息
+ *
+ * @param menu 菜单信息
+ * @return 组件信息
+ */
+ public String getComponent(SysMenu menu) {
+ String component = Constant.LAYOUT;
+ if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) {
+ component = menu.getComponent();
+ } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
+ component = Constant.INNER_LINK;
+ } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) {
+ component = Constant.PARENT_VIEW;
+ }
+ return component;
+ }
+
+ /**
+ * 是否为菜单内部跳转
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ public boolean isMenuFrame(SysMenu menu) {
+ return menu.getParentId().intValue() == 0 && Constant.TYPE_MENU.equals(menu.getMenuType())
+ && menu.getIsFrame().equals(Constant.NO_FRAME);
+ }
+
+ /**
+ * 是否为内链组件
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ public boolean isInnerLink(SysMenu menu) {
+ return menu.getIsFrame().equals(Constant.NO_FRAME) && HttpUtil.isHttp(menu.getPath());
+ }
+
+ /**
+ * 是否为parent_view组件
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ public boolean isParentView(SysMenu menu) {
+ return menu.getParentId().intValue() != 0 && Constant.TYPE_DIR.equals(menu.getMenuType());
+ }
+
+ /**
+ * 根据父节点的ID获取所有子节点
+ *
+ * @param list 分类表
+ * @param parentId 传入的父节点ID
+ * @return String
+ */
+ public List getChildPerms(List list, int parentId) {
+ List returnList = new ArrayList();
+ for (SysMenu t : list) {
+ // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
+ if (t.getParentId() == parentId) {
+ recursionFn(list, t);
+ returnList.add(t);
+ }
+ }
+ return returnList;
+ }
+
+ /**
+ * 递归列表
+ *
+ * @param list
+ * @param t
+ */
+ private void recursionFn(List list, SysMenu t) {
+ // 得到子节点列表
+ List childList = getChildList(list, t);
+ t.setChildren(childList);
+ for (SysMenu tChild : childList) {
+ if (hasChild(list, tChild)) {
+ recursionFn(list, tChild);
+ }
+ }
+ }
+
+ /**
+ * 得到子节点列表
+ */
+ private List getChildList(List list, SysMenu t) {
+ List tlist = new ArrayList();
+ for (SysMenu n : list) {
+ if (n.getParentId().longValue() == t.getMenuId().longValue()) {
+ tlist.add(n);
+ }
+ }
+ return tlist;
+ }
+
+ /**
+ * 判断是否有子节点
+ */
+ private boolean hasChild(List list, SysMenu t) {
+ return getChildList(list, t).size() > 0;
+ }
+
+ /**
+ * 内链域名特殊字符替换
+ *
+ * @return
+ */
+ public String innerLinkReplaceEach(String path) {
+ return StringUtils.replaceEach(path, new String[]{Constant.HTTP, Constant.HTTPS, Constant.WWW, "."},
+ new String[]{"", ""});
+ }
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysRoleServiceImpl.java b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysRoleServiceImpl.java
new file mode 100644
index 00000000..f7d9404f
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/service/auth/impl/SysRoleServiceImpl.java
@@ -0,0 +1,409 @@
+package com.glxp.api.admin.service.auth.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.github.pagehelper.PageHelper;
+import com.glxp.api.admin.constant.Constant;
+import com.glxp.api.admin.dao.auth.SysRoleMapper;
+import com.glxp.api.admin.dao.auth.SysRoleMenuMapper;
+import com.glxp.api.admin.dao.auth.SysUserRoleMapper;
+import com.glxp.api.admin.entity.auth.SysRole;
+import com.glxp.api.admin.entity.auth.SysRoleMenu;
+import com.glxp.api.admin.entity.auth.SysUserRole;
+import com.glxp.api.admin.exception.ServiceException;
+import com.glxp.api.admin.req.auth.SysRoleRequest;
+import com.glxp.api.admin.req.auth.SysUserRoleRequest;
+import com.glxp.api.admin.service.auth.ISysRoleService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * 角色 业务层处理
+ */
+@RequiredArgsConstructor
+@Service
+public class SysRoleServiceImpl implements ISysRoleService {
+
+
+ @Resource
+ SysRoleMapper sysRoleMapper;
+ @Resource
+ SysRoleMenuMapper roleMenuMapper;
+ @Resource
+ SysUserRoleMapper sysUserRoleMapper;
+
+ @Override
+ public List selectPageRoleList(SysRoleRequest sysRoleRequest) {
+
+ if (sysRoleRequest.getPage() != null) {
+ int offset = (sysRoleRequest.getPage() - 1) * sysRoleRequest.getLimit();
+ PageHelper.offsetPage(offset, sysRoleRequest.getLimit());
+ }
+ return sysRoleMapper.selectRoleList(sysRoleRequest);
+ }
+
+ /**
+ * 根据条件分页查询角色数据
+ */
+ @Override
+ public List selectRoleList(SysRoleRequest sysRoleRequest) {
+ return sysRoleMapper.selectRoleList(sysRoleRequest);
+ }
+
+
+ /**
+ * 根据用户ID查询角色
+ */
+ @Override
+ public List selectRolesByUserId(Long userId) {
+ List userRoles = sysRoleMapper.selectRolePermissionByUserId(userId);
+ List roles = selectRoleAll();
+ for (SysRole role : roles) {
+ for (SysRole userRole : userRoles) {
+ if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) {
+ role.setFlag(true);
+ break;
+ }
+ }
+ }
+ return roles;
+ }
+
+ /**
+ * 根据用户ID查询权限
+ *
+ * @param userId 用户ID
+ * @return 权限列表
+ */
+ @Override
+ public Set selectRolePermissionByUserId(Long userId) {
+ List perms = sysRoleMapper.selectRolePermissionByUserId(userId);
+ Set permsSet = new HashSet<>();
+ for (SysRole perm : perms) {
+ if (ObjectUtil.isNotNull(perm)) {
+ permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
+ }
+ }
+ return permsSet;
+ }
+
+ /**
+ * 查询所有角色
+ *
+ * @return 角色列表
+ */
+ @Override
+ public List selectRoleAll() {
+ return this.selectRoleList(new SysRoleRequest());
+ }
+
+ /**
+ * 根据用户ID获取角色选择框列表
+ *
+ * @param userId 用户ID
+ * @return 选中角色ID列表
+ */
+ @Override
+ public List selectRoleListByUserId(Long userId) {
+ return sysRoleMapper.selectRoleListByUserId(userId);
+ }
+
+ /**
+ * 通过角色ID查询角色
+ *
+ * @param roleId 角色ID
+ * @return 角色对象信息
+ */
+ @Override
+ public SysRole selectRoleById(Long roleId) {
+ return sysRoleMapper.selectById(roleId);
+ }
+
+ /**
+ * 校验角色名称是否唯一
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ @Override
+ public String checkRoleNameUnique(SysRole role) {
+
+ SysRoleRequest sysRoleRequest = new SysRoleRequest();
+ sysRoleRequest.setRoleName(role.getRoleName());
+ sysRoleRequest.setNeRoleId(role.getRoleId());
+ List sysRoles = sysRoleMapper.selectRoleList(sysRoleRequest);
+ if (CollUtil.isNotEmpty(sysRoles)) {
+ return Constant.NOT_UNIQUE;
+ } else {
+ return Constant.UNIQUE;
+ }
+ }
+
+ /**
+ * 校验角色权限是否唯一
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ @Override
+ public String checkRoleKeyUnique(SysRole role) {
+
+
+ SysRoleRequest sysRoleRequest = new SysRoleRequest();
+ sysRoleRequest.setRoleKey(role.getRoleKey());
+ sysRoleRequest.setNeRoleId(role.getRoleId());
+ List sysRoles = sysRoleMapper.selectRoleList(sysRoleRequest);
+ if (CollUtil.isNotEmpty(sysRoles)) {
+ return Constant.NOT_UNIQUE;
+ } else {
+ return Constant.UNIQUE;
+ }
+
+
+ }
+
+ /**
+ * 校验角色是否允许操作
+ *
+ * @param role 角色信息
+ */
+ @Override
+ public void checkRoleAllowed(SysRole role) {
+ if (ObjectUtil.isNotNull(role.getRoleId()) && role.isAdmin()) {
+ throw new ServiceException("不允许操作超级管理员角色");
+ }
+ }
+
+ /**
+ * 校验角色是否有数据权限
+ *
+ * @param roleId 角色id
+ */
+ @Override
+ public void checkRoleDataScope(Long roleId) {
+ if (roleId != 1) {
+ SysRoleRequest roleRequest = new SysRoleRequest();
+ roleRequest.setRoleId(roleId);
+ List roles = this.selectRoleList(roleRequest);
+ if (CollUtil.isEmpty(roles)) {
+ throw new ServiceException("没有权限访问角色数据!");
+ }
+ }
+ }
+
+ /**
+ * 通过角色ID查询角色使用数量
+ *
+ * @param roleId 角色ID
+ * @return 结果
+ */
+ @Override
+ public long countUserRoleByRoleId(Long roleId) {
+ List ids = sysUserRoleMapper.selectUserIdsByRoleId(roleId);
+ return ids.size();
+ }
+
+ /**
+ * 新增保存角色信息
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int insertRole(SysRole role) {
+ // 新增角色信息
+ sysRoleMapper.insert(role);
+ return insertRoleMenu(role);
+ }
+
+ /**
+ * 修改保存角色信息
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int updateRole(SysRole role) {
+ // 修改角色信息
+ sysRoleMapper.updateById(role);
+ // 删除角色与菜单关联
+ roleMenuMapper.deleteById(role.getRoleId());
+ return insertRoleMenu(role);
+ }
+
+ /**
+ * 修改角色状态
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ @Override
+ public int updateRoleStatus(SysRole role) {
+ return sysRoleMapper.updateById(role);
+ }
+
+ /**
+ * 修改数据权限信息
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int authDataScope(SysRole role) {
+ // 修改角色信息
+ sysRoleMapper.updateById(role);
+ // 删除角色与部门关联
+// roleDeptMapper.delete(new LambdaQueryWrapper().eq(SysRoleDept::getRoleId, role.getRoleId()));
+// // 新增角色和部门信息(数据权限)
+// return insertRoleDept(role);
+ return 0;
+ }
+
+ /**
+ * 新增角色菜单信息
+ *
+ * @param role 角色对象
+ */
+ public int insertRoleMenu(SysRole role) {
+ int rows = 1;
+ // 新增用户与角色管理
+ List list = new ArrayList();
+ for (Long menuId : role.getMenuIds()) {
+ SysRoleMenu rm = new SysRoleMenu();
+ rm.setRoleId(role.getRoleId());
+ rm.setMenuId(menuId);
+ list.add(rm);
+ }
+ if (list.size() > 0) {
+ roleMenuMapper.insertBatch(list);
+ }
+ return rows;
+ }
+
+ /**
+ * 新增角色部门信息(数据权限)
+ *
+ * @param role 角色对象
+ */
+// public int insertRoleDept(SysRole role) {
+// int rows = 1;
+// // 新增角色与部门(数据权限)管理
+// List list = new ArrayList();
+// for (Long deptId : role.getDeptIds()) {
+// SysRoleDept rd = new SysRoleDept();
+// rd.setRoleId(role.getRoleId());
+// rd.setDeptId(deptId);
+// list.add(rd);
+// }
+// if (list.size() > 0) {
+// rows = roleDeptMapper.insertBatch(list) ? list.size() : 0;
+// }
+// return rows;
+// }
+
+ /**
+ * 通过角色ID删除角色
+ *
+ * @param roleId 角色ID
+ * @return 结果
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int deleteRoleById(Long roleId) {
+ // 删除角色与菜单关联
+ roleMenuMapper.deleteById(roleId);
+ // 删除角色与部门关联
+ return sysRoleMapper.delete(roleId);
+ }
+
+ /**
+ * 批量删除角色信息
+ *
+ * @param roleIds 需要删除的角色ID
+ * @return 结果
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int deleteRoleByIds(Long[] roleIds) {
+ for (Long roleId : roleIds) {
+ checkRoleAllowed(new SysRole(roleId));
+ checkRoleDataScope(roleId);
+ SysRole role = selectRoleById(roleId);
+ if (countUserRoleByRoleId(roleId) > 0) {
+ throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
+ }
+ }
+ List ids = Arrays.asList(roleIds);
+ // 删除角色与菜单关联
+ roleMenuMapper.deleteByList(ids);
+ // 删除角色与部门关联
+// roleDeptMapper.delete(new LambdaQueryWrapper().in(SysRoleDept::getRoleId, ids));
+ return sysRoleMapper.deleteBatchIds(ids);
+ }
+
+ /**
+ * 取消授权用户角色
+ *
+ * @param userRole 用户和角色关联信息
+ * @return 结果
+ */
+ @Override
+ public int deleteAuthUser(SysUserRole userRole) {
+ SysUserRoleRequest sysUserRoleRequest = new SysUserRoleRequest();
+
+ return sysUserRoleMapper.delete(sysUserRoleRequest);
+
+// return sysUserRoleMapper.delete(new LambdaQueryWrapper()
+// .eq(SysUserRole::getRoleId, userRole.getRoleId())
+// .eq(SysUserRole::getUserId, userRole.getUserId()));
+ }
+
+ /**
+ * 批量取消授权用户角色
+ *
+ * @param roleId 角色ID
+ * @param userIds 需要取消授权的用户数据ID
+ * @return 结果
+ */
+ @Override
+ public int deleteAuthUsers(Long roleId, Long[] userIds) {
+
+
+ SysUserRoleRequest sysUserRoleRequest = new SysUserRoleRequest();
+ return sysUserRoleMapper.delete(sysUserRoleRequest);
+// return sysUserRoleMapper.delete(new LambdaQueryWrapper()
+// .eq(SysUserRole::getRoleId, roleId)
+// .in(SysUserRole::getUserId, Arrays.asList(userIds)));
+ }
+
+ /**
+ * 批量选择授权用户角色
+ *
+ * @param roleId 角色ID
+ * @param userIds 需要授权的用户数据ID
+ * @return 结果
+ */
+ @Override
+ public int insertAuthUsers(Long roleId, Long[] userIds) {
+ // 新增用户与角色管理
+ int rows = 1;
+ List list = new ArrayList();
+ for (Long userId : userIds) {
+ SysUserRole ur = new SysUserRole();
+ ur.setUserId(userId);
+ ur.setRoleId(roleId);
+ list.add(ur);
+ }
+ if (list.size() > 0) {
+ sysUserRoleMapper.insertBatch(list);
+ }
+ return rows;
+ }
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/util/ReflectUtils.java b/api-admin/src/main/java/com/glxp/api/admin/util/ReflectUtils.java
new file mode 100644
index 00000000..9799cc5e
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/util/ReflectUtils.java
@@ -0,0 +1,54 @@
+package com.glxp.api.admin.util;
+
+import cn.hutool.core.util.ReflectUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+
+import java.lang.reflect.Method;
+
+/**
+ * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
+ */
+@SuppressWarnings("rawtypes")
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class ReflectUtils extends ReflectUtil {
+
+ private static final String SETTER_PREFIX = "set";
+
+ private static final String GETTER_PREFIX = "get";
+
+ /**
+ * 调用Getter方法.
+ * 支持多级,如:对象名.对象名.方法
+ */
+ @SuppressWarnings("unchecked")
+ public static E invokeGetter(Object obj, String propertyName) {
+ Object object = obj;
+ for (String name : StringUtils.split(propertyName, ".")) {
+ String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+ object = invoke(object, getterMethodName);
+ }
+ return (E) object;
+ }
+
+ /**
+ * 调用Setter方法, 仅匹配方法名。
+ * 支持多级,如:对象名.对象名.方法
+ */
+ public static void invokeSetter(Object obj, String propertyName, E value) {
+ Object object = obj;
+ String[] names = StringUtils.split(propertyName, ".");
+ for (int i = 0; i < names.length; i++) {
+ if (i < names.length - 1) {
+ String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
+ object = invoke(object, getterMethodName);
+ } else {
+ String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
+ Method method = getMethodByName(object.getClass(), setterMethodName);
+ invoke(object, method, value);
+ }
+ }
+ }
+
+}
diff --git a/api-admin/src/main/java/com/glxp/api/admin/util/StreamUtils.java b/api-admin/src/main/java/com/glxp/api/admin/util/StreamUtils.java
new file mode 100644
index 00000000..beafef7f
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/api/admin/util/StreamUtils.java
@@ -0,0 +1,247 @@
+package com.glxp.api.admin.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class StreamUtils {
+
+ /**
+ * 将collection过滤
+ *
+ * @param collection 需要转化的集合
+ * @param function 过滤方法
+ * @return 过滤后的list
+ */
+ public static List filter(Collection collection, Predicate function) {
+ if (CollUtil.isEmpty(collection)) {
+ return CollUtil.newArrayList();
+ }
+ return collection.stream().filter(function).collect(Collectors.toList());
+ }
+
+ /**
+ * 将collection拼接
+ *
+ * @param collection 需要转化的集合
+ * @param function 拼接方法
+ * @return 拼接后的list
+ */
+ public static String join(Collection collection, Function function) {
+ return join(collection, function, ",");
+ }
+
+ /**
+ * 将collection拼接
+ *
+ * @param collection 需要转化的集合
+ * @param function 拼接方法
+ * @param delimiter 拼接符
+ * @return 拼接后的list
+ */
+ public static String join(Collection collection, Function function, CharSequence delimiter) {
+ if (CollUtil.isEmpty(collection)) {
+ return StringUtils.EMPTY;
+ }
+ return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter));
+ }
+
+ /**
+ * 将collection排序
+ *
+ * @param collection 需要转化的集合
+ * @param comparing 排序方法
+ * @return 排序后的list
+ */
+ public static List sorted(Collection collection, Comparator comparing) {
+ if (CollUtil.isEmpty(collection)) {
+ return CollUtil.newArrayList();
+ }
+ return collection.stream().sorted(comparing).collect(Collectors.toList());
+ }
+
+ /**
+ * 将collection转化为类型不变的map
+ * {@code Collection ----> Map}
+ *
+ * @param collection 需要转化的集合
+ * @param key V类型转化为K类型的lambda方法
+ * @param collection中的泛型
+ * @param map中的key类型
+ * @return 转化后的map
+ */
+ public static Map toIdentityMap(Collection collection, Function key) {
+ if (CollUtil.isEmpty(collection)) {
+ return MapUtil.newHashMap();
+ }
+ return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
+ }
+
+ /**
+ * 将Collection转化为map(value类型与collection的泛型不同)
+ * {@code Collection -----> Map }
+ *
+ * @param collection 需要转化的集合
+ * @param key E类型转化为K类型的lambda方法
+ * @param value E类型转化为V类型的lambda方法
+ * @param collection中的泛型
+ * @param map中的key类型
+ * @param map中的value类型
+ * @return 转化后的map
+ */
+ public static Map toMap(Collection collection, Function key, Function value) {
+ if (CollUtil.isEmpty(collection)) {
+ return MapUtil.newHashMap();
+ }
+ return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l));
+ }
+
+ /**
+ * 将collection按照规则(比如有相同的班级id)分类成map
+ * {@code Collection -------> Map> }
+ *
+ * @param collection 需要分类的集合
+ * @param key 分类的规则
+ * @param collection中的泛型
+ * @param map中的key类型
+ * @return 分类后的map
+ */
+ public static Map> groupByKey(Collection collection, Function key) {
+ if (CollUtil.isEmpty(collection)) {
+ return MapUtil.newHashMap();
+ }
+ return collection
+ .stream()
+ .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
+ }
+
+ /**
+ * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map
+ * {@code Collection ---> Map>> }
+ *
+ * @param collection 需要分类的集合
+ * @param key1 第一个分类的规则
+ * @param key2 第二个分类的规则
+ * @param 集合元素类型
+ * @param 第一个map中的key类型
+ * @param 第二个map中的key类型
+ * @return 分类后的map
+ */
+ public static Map>> groupBy2Key(Collection collection, Function key1, Function key2) {
+ if (CollUtil.isEmpty(collection)) {
+ return MapUtil.newHashMap();
+ }
+ return collection
+ .stream()
+ .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList())));
+ }
+
+ /**
+ * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map
+ * {@code Collection ---> Map> }
+ *
+ * @param collection 需要分类的集合
+ * @param key1 第一个分类的规则
+ * @param key2 第二个分类的规则
+ * @param 第一个map中的key类型
+ * @param 第二个map中的key类型
+ * @param collection中的泛型
+ * @return 分类后的map
+ */
+ public static Map> group2Map(Collection collection, Function key1, Function key2) {
+ if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) {
+ return MapUtil.newHashMap();
+ }
+ return collection
+ .stream()
+ .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l)));
+ }
+
+ /**
+ * 将collection转化为List集合,但是两者的泛型不同
+ * {@code Collection ------> List }
+ *
+ * @param collection 需要转化的集合
+ * @param function collection中的泛型转化为list泛型的lambda表达式
+ * @param collection中的泛型
+ * @param List中的泛型
+ * @return 转化后的list
+ */
+ public static List toList(Collection collection, Function function) {
+ if (CollUtil.isEmpty(collection)) {
+ return CollUtil.newArrayList();
+ }
+ return collection
+ .stream()
+ .map(function)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 将collection转化为Set集合,但是两者的泛型不同
+ * {@code Collection ------> Set }
+ *
+ * @param collection 需要转化的集合
+ * @param function collection中的泛型转化为set泛型的lambda表达式
+ * @param collection中的泛型
+ * @param Set中的泛型
+ * @return 转化后的Set
+ */
+ public static Set