page, @Param("vo") SysOperationLogVo sysOperationLogEntity);
+
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleDeptMapper.java b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleDeptMapper.java
new file mode 100644
index 0000000..0835d80
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleDeptMapper.java
@@ -0,0 +1,54 @@
+package com.starry.admin.modules.system.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.starry.admin.modules.system.entity.SysRoleDeptEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+
+/**
+ *
+ * 角色和部门关联表 Mapper 接口
+ *
+ *
+ * @author admin
+ * @since 2022-07-06
+ */
+@Mapper
+public interface SysRoleDeptMapper extends BaseMapper {
+
+ /**
+ * 通过租户ID删除角色和部门关联
+ *
+ * @param tenantId 租户ID
+ * @return 结果
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ int deleteRoleDeptByTenantId(Long tenantId);
+
+ /**
+ * 通过角色ID删除角色和部门关联
+ *
+ * @param roleId 角色ID
+ * @return 结果
+ */
+ int deleteRoleDeptByRoleId(Long roleId);
+
+ /**
+ * 批量新增角色部门信息
+ *
+ * @param roleDeptList 角色部门列表
+ * @return 结果
+ */
+ int batchRoleDept(List roleDeptList);
+
+ /**
+ * 批量删除角色部门关联信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ int deleteRoleDept(Long[] ids);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleMapper.java b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleMapper.java
new file mode 100644
index 0000000..1288979
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleMapper.java
@@ -0,0 +1,88 @@
+package com.starry.admin.modules.system.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.starry.admin.modules.system.entity.SysRoleEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+
+/**
+ *
+ * 角色表 Mapper 接口
+ *
+ *
+ * @author admin
+ * @since 2022-07-01
+ */
+@Mapper
+public interface SysRoleMapper extends BaseMapper {
+
+ /**
+ * 通过角色ID查询角色
+ *
+ * @param roleId 角色ID
+ * @return 角色对象信息
+ */
+ SysRoleEntity selectRoleById(Long roleId);
+
+ /**
+ * 校验角色名称是否唯一
+ *
+ * @param roleName 角色名称
+ * @return 角色信息
+ */
+ SysRoleEntity checkRoleNameUnique(String roleName);
+
+ /**
+ * 校验角色权限是否唯一
+ *
+ * @param roleKey 角色权限
+ * @return 角色信息
+ */
+ SysRoleEntity checkRoleKeyUnique(String roleKey);
+
+ /**
+ * 根据用户ID查询角色
+ *
+ * @param userId 用户ID
+ * @return 角色列表
+ */
+ List selectRolePermissionByUserId(String userId);
+
+ /**
+ * 根据条件分页查询角色数据
+ *
+ * @param role 角色信息
+ * @return 角色数据集合信息
+ */
+ List selectRoleList(SysRoleEntity role);
+
+ /**
+ * 根据租户ID查询默认管理员角色
+ *
+ * @param tenantId 租户ID
+ * @return 角色
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ List queryAdminRole(String tenantId);
+
+ /**
+ * 批量删除角色信息-根据租户
+ *
+ * @param ids 需要删除的租户id
+ * @return 结果
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ int deleteRoleByTenantId(String[] ids);
+
+ /**
+ * 通过角色ID查询角色使用数量
+ *
+ * @param roleId 角色ID
+ * @return 结果
+ */
+ int countUserRoleByRoleId(Long roleId);
+
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleMenuMapper.java b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleMenuMapper.java
new file mode 100644
index 0000000..95f5c7a
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysRoleMenuMapper.java
@@ -0,0 +1,45 @@
+package com.starry.admin.modules.system.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.starry.admin.modules.system.entity.SysRoleMenuEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+
+/**
+ *
+ * 角色和菜单关联表 Mapper 接口
+ *
+ *
+ * @author admin
+ * @since 2022-07-06
+ */
+@Mapper
+public interface SysRoleMenuMapper extends BaseMapper {
+
+ /**
+ * 通过租户ID删除角色和菜单关联
+ *
+ * @param tenantId 租户ID
+ * @return 结果
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ int deleteRoleMenuByTenantId(String tenantId);
+
+ /**
+ * 通过租户ID删除角色和菜单关联
+ *
+ * @param ids 租户ID
+ * @return 结果
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ int deleteRoleMenuByTenantIds(String[] ids);
+
+ /**
+ * 批量删除角色菜单关联信息
+ *
+ * @param ids 需要删除的数据ID
+ * @return 结果
+ */
+ int deleteRoleMenu(Long[] ids);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysUserMapper.java b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysUserMapper.java
new file mode 100644
index 0000000..a4a8cdf
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysUserMapper.java
@@ -0,0 +1,85 @@
+package com.starry.admin.modules.system.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.starry.admin.modules.system.entity.SysUserEntity;
+import com.starry.admin.modules.system.vo.RoleUserResultVo;
+import com.starry.admin.modules.system.vo.SysUserQueryVo;
+import com.starry.admin.modules.system.vo.UserQueryVo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ *
+ * 后台用户表 Mapper 接口
+ *
+ *
+ * @author admin
+ * @since 2021-09-03
+ */
+@Mapper
+public interface SysUserMapper extends BaseMapper {
+
+
+ /**
+ * 通过用户ID查询用户
+ *
+ * @param userId 用户ID
+ * @return 用户对象信息
+ */
+ SysUserEntity selectUserById(String userId);
+
+ /**
+ * 根据条件分页查询用户列表
+ *
+ * @param queryVo 条件信息
+ * @param page 分页信息
+ * @return 用户信息集合信息
+ */
+ IPage selectUserList(IPage page, @Param("user") UserQueryVo queryVo);
+
+ /**
+ * 通过用户名查询用户
+ *
+ * @param userName 用户名
+ * @return 用户对象信息
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ SysUserEntity selectUserByUserName(String userName);
+
+ /**
+ * 校验用户名称是否唯一
+ *
+ * @param userName 用户名称
+ * @return 结果
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ int checkUserNameUnique(String userName);
+
+ /**
+ * 批量删除用户信息-根据租户
+ *
+ * @param ids 需要删除的租户ID
+ * @return 结果
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ int deleteUserByTenantId(String[] ids);
+
+ /**
+ * 根据条件分页查询已配用户角色列表
+ *
+ * @param user 用户信息
+ * @return 用户信息集合信息
+ */
+ IPage selectAllocatedList(Page page, @Param("query") SysUserQueryVo user);
+
+ /**
+ * 根据条件分页查询未配用户角色列表
+ *
+ * @param user 用户信息
+ * @return 用户信息集合信息
+ */
+ IPage selectUnallocatedList(Page page, @Param("query") SysUserQueryVo user);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysUserRoleMapper.java b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysUserRoleMapper.java
new file mode 100644
index 0000000..8b52a13
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/mapper/SysUserRoleMapper.java
@@ -0,0 +1,46 @@
+package com.starry.admin.modules.system.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.starry.admin.modules.system.entity.SysUserRoleEntity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+
+/**
+ *
+ * 用户角色关联表 Mapper 接口
+ *
+ *
+ * @author admin
+ * @since 2022-07-08
+ */
+@Mapper
+public interface SysUserRoleMapper extends BaseMapper {
+
+ /**
+ * 批量删除用户和角色关联-根据租户
+ *
+ * @param ids 需要删除的用户租户id
+ * @return 结果
+ */
+ @InterceptorIgnore(tenantLine = "1")
+ int deleteUserRoleByTenantId(String[] ids);
+
+ /**
+ * 删除用户和角色关联信息
+ *
+ * @param userRole 用户和角色关联信息
+ * @return 结果
+ */
+ int deleteUserRoleInfo(SysUserRoleEntity userRole);
+
+ /**
+ * 批量取消授权用户角色
+ *
+ * @param roleId 角色ID
+ * @param userIds 需要删除的用户数据ID
+ * @return 结果
+ */
+ int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") String[] userIds);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysDictDataService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysDictDataService.java
new file mode 100644
index 0000000..90dbef5
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysDictDataService.java
@@ -0,0 +1,71 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.modules.system.entity.SysDictDataEntity;
+import com.starry.admin.modules.system.vo.SysDictDataVo;
+
+import java.util.List;
+
+/**
+ * 字典数据表Service接口
+ *
+ * @author admin
+ */
+public interface ISysDictDataService extends IService {
+ /**
+ * 查询字典数据表
+ *
+ * @param dictDataId 字典数据表主键
+ * @return 字典数据表
+ */
+ SysDictDataEntity selectXlDictDataByDictDataId(Long dictDataId);
+
+ /**
+ * 查询字典数据表列表
+ *
+ * @param sysDictDataEntity 字典数据表
+ * @return 字典数据表集合
+ */
+ IPage selectXlDictDataList(SysDictDataVo sysDictDataEntity);
+
+ /**
+ * 新增字典数据表
+ *
+ * @param sysDictDataEntity 字典数据表
+ * @return 结果
+ */
+ boolean create(SysDictDataEntity sysDictDataEntity);
+
+ /**
+ * 修改字典数据表
+ *
+ * @param sysDictDataEntity 字典数据表
+ * @return 结果
+ */
+ boolean update(SysDictDataEntity sysDictDataEntity);
+
+ /**
+ * 批量删除字典数据表
+ *
+ * @param dictDataIds 需要删除的字典数据表主键集合
+ * @return 结果
+ */
+ int deleteXlDictDataByDictDataIds(Long[] dictDataIds);
+
+ /**
+ * 删除字典数据表信息
+ *
+ * @param dictDataId 字典数据表主键
+ * @return 结果
+ */
+ int deleteXlDictDataByDictDataId(Long dictDataId);
+
+ /**
+ * 根据字典类型查询字典数据
+ *
+ * @param dictType 字典类型
+ * @return 字典数据集合信息
+ */
+ List selectDictDataByType(String dictType);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysDictService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysDictService.java
new file mode 100644
index 0000000..8bbd65c
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysDictService.java
@@ -0,0 +1,87 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.modules.system.entity.SysDictEntity;
+import com.starry.admin.modules.system.vo.SysDictVo;
+
+import java.util.List;
+
+/**
+ * 字典表Service接口
+ *
+ * @author admin
+ * @since 2022-08-09
+ */
+public interface ISysDictService extends IService {
+ /**
+ * 查询字典表
+ *
+ * @param dictId 字典表主键
+ * @return 字典表
+ */
+ SysDictEntity selectXlDictByDictId(Long dictId);
+
+ /**
+ * 查询字典表列表
+ *
+ * @param sysDictVo 字典表
+ * @return 字典表集合
+ */
+ Page selectXlDictList(SysDictVo sysDictVo);
+
+ /**
+ * 新增字典表
+ *
+ * @param sysDictEntity 字典表
+ * @return 结果
+ */
+ boolean create(SysDictEntity sysDictEntity);
+
+ /**
+ * 修改字典表
+ *
+ * @param sysDictEntity 字典表
+ * @return 结果
+ */
+ boolean update(SysDictEntity sysDictEntity);
+
+ /**
+ * 批量删除字典表
+ *
+ * @param dictIds 需要删除的字典表主键集合
+ * @return 结果
+ */
+ int deleteXlDictByDictIds(Long[] dictIds);
+
+ /**
+ * 删除字典表信息
+ *
+ * @param dictId 字典表主键
+ * @return 结果
+ */
+ int deleteXlDictByDictId(Long dictId);
+
+ /**
+ * 根据所有字典类型
+ *
+ * @return 字典类型集合信息
+ */
+ List selectDictTypeAll();
+
+ /**
+ * 加载字典缓存数据
+ */
+ void loadingDictCache();
+
+ /**
+ * 清空字典缓存数据
+ */
+ void clearDictCache();
+
+ /**
+ * 重置字典缓存数据
+ */
+ void resetDictCache();
+
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysLoginLogService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysLoginLogService.java
new file mode 100644
index 0000000..e5470d8
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysLoginLogService.java
@@ -0,0 +1,66 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.modules.system.entity.SysLoginLogEntity;
+import com.starry.admin.modules.system.entity.SysLoginLogVo;
+
+/**
+ * 系统访问日志表Service接口
+ *
+ * @author admin
+ */
+public interface ISysLoginLogService extends IService {
+ /**
+ * 查询系统访问日志表
+ *
+ * @param loginId 系统访问日志表主键
+ * @return 系统访问日志表
+ */
+ SysLoginLogEntity selectXlLoginLogByLoginId(Long loginId);
+
+ /**
+ * 查询系统访问日志表列表
+ *
+ * @param sysLoginLogEntity 系统访问日志表
+ * @return 系统访问日志表集合
+ */
+ IPage selectXlLoginLogList(SysLoginLogVo sysLoginLogEntity);
+
+ /**
+ * 新增系统访问日志表
+ *
+ * @param sysLoginLogEntity 系统访问日志表
+ * @return 结果
+ */
+ boolean create(SysLoginLogEntity sysLoginLogEntity);
+
+ /**
+ * 修改系统访问日志表
+ *
+ * @param sysLoginLogEntity 系统访问日志表
+ * @return 结果
+ */
+ boolean update(SysLoginLogEntity sysLoginLogEntity);
+
+ /**
+ * 批量删除系统访问日志表
+ *
+ * @param loginIds 需要删除的系统访问日志表主键集合
+ * @return 结果
+ */
+ int deleteXlLoginLogByLoginIds(Long[] loginIds);
+
+ /**
+ * 删除系统访问日志表信息
+ *
+ * @param loginId 系统访问日志表主键
+ * @return 结果
+ */
+ int deleteXlLoginLogByLoginId(Long loginId);
+
+ /**
+ * 清空系统登录日志
+ */
+ void cleanLoginlog();
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysOperationLogService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysOperationLogService.java
new file mode 100644
index 0000000..c8c882f
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/ISysOperationLogService.java
@@ -0,0 +1,61 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.modules.system.entity.SysOperationLogEntity;
+import com.starry.admin.modules.system.vo.SysOperationLogVo;
+
+/**
+ * 操作日志表Service接口
+ *
+ * @author admin
+ */
+public interface ISysOperationLogService extends IService {
+ /**
+ * 查询操作日志表
+ *
+ * @param operId 操作日志表主键
+ * @return 操作日志表
+ */
+ SysOperationLogEntity selectXlOperLogByOperId(Long operId);
+
+ /**
+ * 查询操作日志表列表
+ *
+ * @param sysOperationLogEntity 操作日志表
+ * @return 操作日志表集合
+ */
+ IPage selectXlOperLogList(SysOperationLogVo sysOperationLogEntity);
+
+ /**
+ * 新增操作日志表
+ *
+ * @param sysOperationLogEntity 操作日志表
+ * @return 结果
+ */
+ boolean create(SysOperationLogEntity sysOperationLogEntity);
+
+ /**
+ * 修改操作日志表
+ *
+ * @param sysOperationLogEntity 操作日志表
+ * @return 结果
+ */
+ boolean updateXlOperLog(SysOperationLogEntity sysOperationLogEntity);
+
+ /**
+ * 批量删除操作日志表
+ *
+ * @param operIds 需要删除的操作日志表主键集合
+ * @return 结果
+ */
+ int deleteXlOperLogByOperIds(Long[] operIds);
+
+ /**
+ * 删除操作日志表信息
+ *
+ * @param operId 操作日志表主键
+ * @return 结果
+ */
+ int deleteXlOperLogByOperId(Long operId);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/LoginService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/LoginService.java
new file mode 100644
index 0000000..a81f6cd
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/LoginService.java
@@ -0,0 +1,55 @@
+package com.starry.admin.modules.system.service;
+
+
+import com.starry.admin.common.domain.LoginUser;
+import com.starry.admin.modules.system.entity.SysUserEntity;
+
+import java.util.Set;
+
+/**
+ * @author admin
+ */
+public interface LoginService {
+
+ /**
+ * 登录功能
+ *
+ * @param username 用户名
+ * @param password 密码
+ * @return 生成的JWT的token
+ */
+ String login(String username, String password);
+
+ /**
+ * 获取菜单数据权限
+ *
+ * @param user 用户信息
+ * @return 菜单权限信息
+ */
+ Set getMenuPermission(SysUserEntity user);
+
+ /**
+ * 获取角色数据权限
+ *
+ * @param user 用户信息
+ * @return 角色权限信息
+ */
+ Set getRolePermission(SysUserEntity user);
+
+ /**
+ * 登录功能
+ *
+ * @param username 用户名
+ * @param password 密码
+ * @return 生成的JWT的token
+ */
+ LoginUser newLogin(String username, String password);
+
+ /**
+ * 新登录功能,增加租户相关
+ *
+ * @param userName 用户名
+ * @return 获取信息
+ */
+ LoginUser getLoginUserInfo(String userName);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/SysDeptService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysDeptService.java
new file mode 100644
index 0000000..bc8f1ac
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysDeptService.java
@@ -0,0 +1,90 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.common.domain.TreeSelect;
+import com.starry.admin.modules.system.entity.SysDeptEntity;
+
+import java.util.List;
+
+/**
+ *
+ * 部门表 服务类
+ *
+ *
+ * @author admin
+ * @since 2022-07-12
+ */
+public interface SysDeptService extends IService {
+
+ /**
+ * 查询部门管理数据
+ *
+ * @param dept 部门信息
+ * @return 部门信息集合
+ */
+ List selectDeptList(SysDeptEntity dept);
+
+ /**
+ * 校验部门名称是否唯一
+ *
+ * @param dept 部门信息
+ * @return 结果
+ */
+ String checkDeptNameUnique(SysDeptEntity dept);
+
+ /**
+ * 添加部门
+ *
+ * @param dept
+ * @return boolean
+ **/
+ boolean create(SysDeptEntity dept);
+
+ /**
+ * 修改部门
+ *
+ * @param dept
+ * @return boolean
+ **/
+ boolean update(SysDeptEntity dept);
+
+ /**
+ * 批量删除部门
+ *
+ * @param ids
+ * @return boolean
+ **/
+ boolean delete(List ids);
+
+ /**
+ * 是否存在部门子节点
+ *
+ * @param deptId 部门ID
+ * @return 结果
+ */
+ boolean hasChildByDeptId(Long deptId);
+
+ /**
+ * 构建前端所需要树结构
+ *
+ * @param depts 部门列表
+ * @return 树结构列表
+ */
+ List buildDeptTreeSelect(List depts);
+
+ /**
+ * 根据角色ID查询部门树信息
+ *
+ * @param roleId 角色ID
+ * @return 选中部门列表
+ */
+ List selectDeptListByRoleId(Long roleId);
+
+ /**
+ * 查询部门树结构信息
+ *
+ * @param dept 部门信息
+ * @return 部门树信息集合
+ */
+ List selectDeptTreeList(SysDeptEntity dept);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/SysMenuService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysMenuService.java
new file mode 100644
index 0000000..576c3a7
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysMenuService.java
@@ -0,0 +1,130 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.common.domain.TreeSelect;
+import com.starry.admin.modules.system.entity.SysMenuEntity;
+import com.starry.admin.modules.system.vo.RouterVo;
+import com.starry.admin.modules.system.vo.SimpleMenu;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ * 菜单表 服务类
+ *
+ *
+ * @author admin
+ * @since 2022-07-03
+ */
+public interface SysMenuService extends IService {
+
+ /**
+ * 添加菜单
+ *
+ * @param menu
+ * @return boolean
+ **/
+ boolean create(SysMenuEntity menu);
+
+ /**
+ * 根据用户查询系统菜单列表
+ *
+ * @param menu 菜单
+ * @param userId 用户ID
+ * @param pageSize 页大小
+ * @param pageNum 页数
+ * @return 分页菜单列表
+ */
+ Page listPage(SysMenuEntity menu, String userId, Integer pageSize, Integer pageNum);
+
+ /**
+ * 根据用户查询系统菜单列表
+ *
+ * @param menu 菜单
+ * @param userId 用户ID
+ * @return 菜单列表
+ */
+ List selectMenuList(SysMenuEntity menu, String userId);
+
+ /**
+ * 根据用户查询系统菜单列表
+ *
+ * @param userId 用户ID
+ * @return 菜单列表
+ */
+ List selectMenuList(String userId);
+
+ /**
+ * 校验菜单名称是否唯一
+ *
+ * @param menu 菜单信息
+ * @return 结果
+ */
+ String checkMenuNameUnique(SysMenuEntity menu);
+
+ /**
+ * 是否存在菜单子节点
+ *
+ * @param menuId 菜单ID
+ * @return 结果 true 存在 false 不存在
+ */
+ boolean hasChildByMenuId(Long menuId);
+
+ /**
+ * 构建前端所需要下拉树结构
+ *
+ * @param menus 菜单列表
+ * @return 下拉树结构列表
+ */
+ List buildMenuTreeSelect(List menus);
+
+ /**
+ * 根据菜单ID查询信息
+ *
+ * @param menuId 菜单ID
+ * @return 菜单信息
+ */
+ SysMenuEntity selectMenuById(Long menuId);
+
+ /**
+ * 根据角色ID查询菜单树信息
+ *
+ * @param roleId 角色ID
+ * @return 选中菜单列表
+ */
+ List selectMenuListByRoleId(Long roleId);
+
+ /**
+ * 根据用户ID查询权限
+ *
+ * @param userId 用户ID
+ * @return 权限列表
+ */
+ Set selectMenuPermsByUserId(String userId);
+
+ /**
+ * 根据用户ID查询菜单树信息
+ *
+ * @param userId 用户ID
+ * @return 菜单列表
+ */
+ List selectMenuTreeByUserId(String userId);
+
+ /**
+ * 构建前端路由所需要的菜单
+ *
+ * @param menus 菜单列表
+ * @return 路由列表
+ */
+ List buildMenus(List menus);
+
+ /**
+ * 查询所有开启状态菜单精简信息
+ *
+ * @return 菜单列表
+ */
+ List selectSimpleMenuList();
+
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/SysRoleMenuService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysRoleMenuService.java
new file mode 100644
index 0000000..42d3760
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysRoleMenuService.java
@@ -0,0 +1,17 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.modules.system.entity.SysRoleMenuEntity;
+
+
+/**
+ *
+ * 角色和菜单关联表 服务类
+ *
+ *
+ * @author admin
+ * @since 2022-07-06
+ */
+public interface SysRoleMenuService extends IService {
+
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/SysRoleService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysRoleService.java
new file mode 100644
index 0000000..d33a048
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysRoleService.java
@@ -0,0 +1,151 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.modules.system.entity.SysRoleEntity;
+import com.starry.admin.modules.system.entity.SysUserRoleEntity;
+
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ *
+ * 角色表 服务类
+ *
+ *
+ * @author admin
+ * @since 2022-07-01
+ */
+public interface SysRoleService extends IService {
+
+ /**
+ * 校验角色名称是否唯一
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ String checkRoleNameUnique(SysRoleEntity role);
+
+ /**
+ * 校验角色权限是否唯一
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ String checkRoleKeyUnique(SysRoleEntity role);
+
+ /**
+ * 添加角色
+ *
+ * @param role
+ * @return boolean
+ **/
+ boolean create(SysRoleEntity role);
+
+ /**
+ * 修改角色
+ *
+ * @param role
+ * @return boolean
+ **/
+ boolean updateRole(SysRoleEntity role);
+
+ /**
+ * 通过角色ID查询角色使用数量
+ *
+ * @param roleId 角色ID
+ * @return 结果
+ */
+ int countUserRoleByRoleId(Long roleId);
+
+ /**
+ * 批量删除角色
+ *
+ * @param roleIds
+ * @return boolean
+ **/
+ boolean delete(Long[] roleIds);
+
+ /**
+ * 分页获取角色列表
+ *
+ * @param keyword
+ * @param pageSize
+ * @param pageNum
+ * @return Page
+ **/
+ Page list(String keyword, Integer pageSize, Integer pageNum);
+
+ /**
+ * 分配菜单权限信息
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ boolean authRoleMenu(SysRoleEntity role);
+
+ /**
+ * 根据用户ID查询角色权限
+ *
+ * @param userId 用户ID
+ * @return 权限列表
+ */
+ Set selectRolePermissionByUserId(String userId);
+
+ /**
+ * 根据条件分页查询角色数据
+ *
+ * @param role 角色信息
+ * @return 角色数据集合信息
+ */
+ List selectRoleList(SysRoleEntity role);
+
+ /**
+ * 校验角色是否允许操作
+ *
+ * @param role 角色信息
+ */
+ void checkRoleAllowed(SysRoleEntity role);
+
+ /**
+ * 校验角色是否有数据权限
+ *
+ * @param roleId 角色id
+ */
+ void checkRoleDataScope(Long roleId);
+
+ /**
+ * 修改数据权限信息
+ *
+ * @param role 角色信息
+ * @return 结果
+ */
+ int authDataScope(SysRoleEntity role);
+
+ /**
+ * 取消授权用户角色
+ *
+ * @param userRole 用户和角色关联信息
+ * @return 结果
+ */
+ int deleteAuthUser(SysUserRoleEntity userRole);
+
+ /**
+ * 批量取消授权用户角色
+ *
+ * @param roleId 角色ID
+ * @param userIds 需要取消授权的用户数据ID
+ * @return 结果
+ */
+ int deleteAuthUsers(Long roleId, String[] userIds);
+
+ /**
+ * 批量选择授权用户角色
+ *
+ * @param roleId 角色ID
+ * @param userIds 需要删除的用户数据ID
+ * @return 结果
+ */
+ int insertAuthUsers(Long roleId, String[] userIds);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/SysUserRoleService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysUserRoleService.java
new file mode 100644
index 0000000..2bcc455
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysUserRoleService.java
@@ -0,0 +1,17 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.modules.system.entity.SysUserRoleEntity;
+
+
+/**
+ *
+ * 用户角色关联表 服务类
+ *
+ *
+ * @author admin
+ * @since 2022-07-08
+ */
+public interface SysUserRoleService extends IService {
+
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/SysUserService.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysUserService.java
new file mode 100644
index 0000000..8a93ffb
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/SysUserService.java
@@ -0,0 +1,126 @@
+package com.starry.admin.modules.system.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.starry.admin.modules.system.entity.SysUserEntity;
+import com.starry.admin.modules.system.vo.RoleUserResultVo;
+import com.starry.admin.modules.system.vo.SysUserQueryVo;
+import com.starry.admin.modules.system.vo.UserQueryVo;
+
+import java.util.List;
+
+/**
+ *
+ * 后台用户表 服务类
+ *
+ *
+ * @author admin
+ * @since 2021-09-03
+ */
+public interface SysUserService extends IService {
+
+ /**
+ * 注册功能
+ *
+ * @param user
+ * @return SysUserEntity
+ */
+ SysUserEntity register(SysUserEntity user);
+
+ /**
+ * 查询用户
+ *
+ * @param userCode
+ * @return SysUserEntity
+ */
+ SysUserEntity getUserByCode(String userCode);
+
+ /**
+ * 通过用户名查询用户
+ *
+ * @param userName 用户名
+ * @return 用户对象信息
+ */
+ SysUserEntity selectUserByUserName(String userName);
+
+ /**
+ * 获取列表。分页
+ *
+ * @param queryVo 查询参数
+ * @return page
+ */
+ IPage listMemberPage(UserQueryVo queryVo);
+
+ /**
+ * 校验用户名称是否唯一
+ *
+ * @param userName 用户名称
+ * @return 结果
+ */
+ String checkUserNameUnique(String userName);
+
+ /**
+ * 添加用户
+ *
+ * @param user
+ * @return boolean
+ **/
+ boolean create(SysUserEntity user);
+
+ /**
+ * 修改用户
+ *
+ * @param user
+ * @return boolean
+ **/
+ boolean update(SysUserEntity user);
+
+ /**
+ * 批量删除用户
+ *
+ * @param ids
+ * @return boolean
+ **/
+ boolean delete(List ids);
+
+ /**
+ * 通过用户ID查询用户
+ *
+ * @param userId 用户ID
+ * @return 用户对象信息
+ */
+ SysUserEntity selectUserById(String userId);
+
+ /**
+ * 根据用户ID查询用户所属角色组
+ *
+ * @param userId 用户id
+ * @return 结果
+ */
+ String selectUserRoleGroup(String userId);
+
+ /**
+ * 修改用户头像
+ *
+ * @param userId 用户id
+ * @param avatar 头像地址
+ * @return 结果
+ */
+ boolean updateUserAvatar(String userId, String avatar);
+
+ /**
+ * 根据条件分页查询已配用户角色列表
+ *
+ * @param user 用户信息
+ * @return 用户信息集合信息
+ */
+ IPage selectAllocatedList(SysUserQueryVo user);
+
+ /**
+ * 根据条件分页查询已配用户角色列表
+ *
+ * @param user 用户信息
+ * @return 用户信息集合信息
+ */
+ IPage selectUnallocatedList(SysUserQueryVo user);
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/LoginServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/LoginServiceImpl.java
new file mode 100644
index 0000000..fb7f225
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/LoginServiceImpl.java
@@ -0,0 +1,183 @@
+package com.starry.admin.modules.system.service.impl;
+
+
+import cn.hutool.core.convert.Convert;
+import com.starry.admin.common.component.JwtToken;
+import com.starry.admin.common.domain.LoginUser;
+import com.starry.admin.common.exception.ServiceException;
+import com.starry.admin.common.security.entity.JwtUser;
+import com.starry.admin.manager.AsyncManager;
+import com.starry.admin.manager.factory.AsyncFactory;
+import com.starry.admin.modules.platform.entity.SysTenantEntity;
+import com.starry.admin.modules.platform.service.ISysTenantService;
+import com.starry.admin.modules.system.entity.SysUserEntity;
+import com.starry.admin.modules.system.service.LoginService;
+import com.starry.admin.modules.system.service.SysMenuService;
+import com.starry.admin.modules.system.service.SysRoleService;
+import com.starry.admin.modules.system.service.SysUserService;
+import com.starry.admin.utils.SecurityUtils;
+import com.starry.common.constant.Constants;
+import com.starry.common.constant.UserConstants;
+import com.starry.common.utils.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author admin
+ */
+@Slf4j
+@Service
+public class LoginServiceImpl implements LoginService {
+
+ @Resource
+ private PasswordEncoder passwordEncoder;
+ @Resource
+ private UserDetailsService userDetailsService;
+ @Resource
+ private JwtToken jwtTokenUtil;
+ @Resource
+ private SysMenuService menuService;
+ @Resource
+ private SysRoleService roleService;
+ @Resource
+ private SysUserService sysUserService;
+ @Resource
+ private ISysTenantService SysTenantService;
+
+ @Override
+ public String login(String username, String password) {
+ String token = null;
+ try {
+ UserDetails userDetails = userDetailsService.loadUserByUsername(username);
+ if (!passwordEncoder.matches(password, userDetails.getPassword())) {
+ throw new BadCredentialsException("密码不正确");
+ }
+ UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ // 登录成功记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_SUCCESS, "登录成功"));
+ JwtUser jwtUser = (JwtUser) authentication.getPrincipal();
+ token = jwtTokenUtil.createToken(jwtUser);
+ } catch (AuthenticationException e) {
+ log.warn("登录异常:{}", e.getMessage());
+ // 登录失败记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, e.getMessage()));
+ }
+ return token;
+ }
+
+ @Override
+ public Set getMenuPermission(SysUserEntity user) {
+ Set perms = new HashSet<>();
+ // 超级管理员拥有所有权限
+ if (SecurityUtils.isAdmin(user.getUserId())) {
+ perms.add("*:*:*");
+ } else {
+ perms = menuService.selectMenuPermsByUserId(user.getUserId());
+ }
+ return perms;
+ }
+
+ @Override
+ public Set getRolePermission(SysUserEntity user) {
+ Set roles = new HashSet<>();
+ // 超级管理员拥有所有权限
+ if (SecurityUtils.isAdmin(user.getUserId())) {
+ roles.add("admin");
+ } else {
+ roles = roleService.selectRolePermissionByUserId(user.getUserId());
+ }
+ return roles;
+ }
+
+ @Override
+ public LoginUser newLogin(String username, String password) {
+ // 用户名或密码为空 错误
+ if (StringUtils.isAnyBlank(username, password)) {
+ // 登录记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名/密码必须填写"));
+ throw new ServiceException("用户/密码必须填写");
+ }
+ // 密码如果不在指定范围内 错误
+ if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+ || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
+ // 登录记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"));
+ throw new ServiceException("用户密码不在指定范围");
+ }
+ // 用户名不在指定范围内 错误
+ if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+ || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
+ // 登录记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名不在指定范围"));
+ throw new ServiceException("用户名不在指定范围");
+ }
+ LoginUser userInfo = this.getLoginUserInfo(username);
+ if (userInfo == null) {
+ // 登录记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户名不存在"));
+ throw new ServiceException("用户名不存在");
+ }
+ SysUserEntity user = userInfo.getUser();
+ if (!SecurityUtils.matchesPassword(password, user.getPassWord())) {
+ // 登录记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "密码错误"));
+ throw new ServiceException("密码错误");
+ }
+ // 线程塞入租户ID
+ SecurityUtils.setTenantId(Convert.toStr(user.getTenantId()));
+ if (user.getStatus() == 1) {
+ // 登录记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"));
+ throw new ServiceException("对不起,您的账号:" + username + " 已停用,请联系管理员");
+ }
+ // 先查询是否被停用了租户
+ if (userInfo.getTenantStatus() != null && userInfo.getTenantStatus() == 1) {
+ // 登录记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "当前租户已经被停用,请联系管理员"));
+ throw new ServiceException("当前租户已经被停用,请联系管理员");
+ }
+ if (userInfo.getTenantEndDate() != null && userInfo.getTenantEndDate().compareTo(new Date()) < 0) {
+ // 登录记录日志
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_FAIL, "当前租户已超过租赁日期,请联系管理员"));
+ throw new ServiceException("当前租户已超过租赁日期,请联系管理员");
+ }
+ AsyncManager.me().execute(AsyncFactory.recordLoginLog(username, Constants.LOGIN_SUCCESS, "登录成功"));
+ return userInfo;
+ }
+
+ @Override
+ public LoginUser getLoginUserInfo(String userName) {
+ SysUserEntity sysUser = sysUserService.selectUserByUserName(userName);
+ if (StringUtils.isNotNull(sysUser)) {
+ // 角色集合
+ Set roles = this.getRolePermission(sysUser);
+ // 权限集合
+ Set permissions = this.getMenuPermission(sysUser);
+ // 查询租户信息
+ SysTenantEntity tenant = SysTenantService.selectSysTenantByTenantId(sysUser.getTenantId());
+ LoginUser sysUserVo = new LoginUser();
+ sysUserVo.setUser(sysUser);
+ sysUserVo.setRoles(roles);
+ sysUserVo.setPermissions(permissions);
+ if (tenant != null) {
+ sysUserVo.setTenantEndDate(tenant.getTenantTime());
+ sysUserVo.setTenantStatus(Integer.valueOf(tenant.getTenantStatus()));
+ }
+ return sysUserVo;
+ }
+ return null;
+ }
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDeptServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDeptServiceImpl.java
new file mode 100644
index 0000000..4f3e92d
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDeptServiceImpl.java
@@ -0,0 +1,195 @@
+package com.starry.admin.modules.system.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.starry.admin.common.domain.TreeSelect;
+import com.starry.admin.modules.system.entity.SysDeptEntity;
+import com.starry.admin.modules.system.entity.SysRoleEntity;
+import com.starry.admin.modules.system.mapper.SysDeptMapper;
+import com.starry.admin.modules.system.mapper.SysRoleMapper;
+import com.starry.admin.modules.system.service.SysDeptService;
+import com.starry.common.annotation.DataScope;
+import com.starry.common.constant.UserConstants;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * 部门表 服务实现类
+ *
+ *
+ * @author admin
+ * @since 2022-07-12
+ */
+@Service
+public class SysDeptServiceImpl extends ServiceImpl implements SysDeptService {
+
+ @Resource
+ private SysRoleMapper roleMapper;
+
+ @Override
+ @DataScope(deptAlias = "d")
+ public List selectDeptList(SysDeptEntity dept) {
+ return baseMapper.selectDeptList(dept);
+ }
+
+ @Override
+ public String checkDeptNameUnique(SysDeptEntity dept) {
+ Long deptId = dept.getDeptId() == null ? -1L : dept.getDeptId();
+ List infos = list(new LambdaQueryWrapper()
+ .eq(SysDeptEntity::getDeptName, dept.getDeptName())
+ .eq(SysDeptEntity::getParentId, dept.getParentId()));
+ // 查出有数据 并且不是自己,则不唯一
+ if (CollectionUtil.isNotEmpty(infos) && infos.get(0).getDeptId().longValue() != deptId.longValue()) {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ @Override
+ public boolean create(SysDeptEntity dept) {
+ SysDeptEntity info = getById(dept.getParentId());
+ // 若父节点不为正常状态,则不允许新增子节点
+ if (!UserConstants.DEPT_NORMAL.equals(String.valueOf(info.getStatus()))) {
+ throw new RuntimeException("部门停用,不允许新增");
+ }
+ dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
+ dept.setDeptLevel(info.getDeptLevel() == null ? 0 : info.getDeptLevel() + 1);
+ return save(dept);
+ }
+
+ @Override
+ public boolean update(SysDeptEntity dept) {
+ // 新的上级部门
+ SysDeptEntity newParentDept = getById(dept.getParentId());
+ // 当前部门
+ SysDeptEntity oldDept = getById(dept.getDeptId());
+ if (newParentDept != null && oldDept != null) {
+ String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
+ String oldAncestors = oldDept.getAncestors();
+ dept.setAncestors(newAncestors);
+ updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
+ }
+ return updateById(dept);
+ }
+
+ @Override
+ public boolean delete(List ids) {
+ return removeBatchByIds(ids);
+ }
+
+ @Override
+ public boolean hasChildByDeptId(Long deptId) {
+ List list = baseMapper.selectList(new LambdaQueryWrapper().eq(SysDeptEntity::getParentId, deptId));
+ if (CollectionUtil.isNotEmpty(list)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List buildDeptTreeSelect(List depts) {
+ List deptList = buildDeptTree(depts);
+ // 转换成树结构的list
+ return deptList.stream().map(TreeSelect::new).collect(Collectors.toList());
+ }
+
+ public List buildDeptTree(List depts) {
+ List returnList = new ArrayList<>();
+ // 所有部门id
+ List tempList = new ArrayList<>();
+ for (SysDeptEntity dept : depts) {
+ tempList.add(dept.getDeptId());
+ }
+ for (SysDeptEntity dept : depts) {
+ // 如若是顶级节点,遍历该父节点下的所有子节点
+ if (!tempList.contains(dept.getParentId())) {
+ recursionFn(depts, dept);
+ returnList.add(dept);
+ }
+ }
+ if (CollectionUtil.isEmpty(returnList)) {
+ returnList = depts;
+ }
+ return returnList;
+ }
+
+ /**
+ * 修改子元素关系
+ *
+ * @param deptId 被修改的部门ID
+ * @param newAncestors 新的父ID集合
+ * @param oldAncestors 旧的父ID集合
+ */
+ public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
+ List childrens = baseMapper.selectChildrenDeptById(deptId);
+ if (CollectionUtil.isNotEmpty(childrens)) {
+ for (SysDeptEntity child : childrens) {
+ child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
+ updateById(child);
+ }
+ }
+ }
+
+ /**
+ * 递归列表
+ */
+ private void recursionFn(List list, SysDeptEntity t) {
+ List childList = getChildList(list, t);
+ t.setChildren(childList);
+ for (SysDeptEntity tChild : childList) {
+ if (hasChild(list, tChild)) {
+ recursionFn(list, tChild);
+ }
+ }
+ }
+
+ /**
+ * 得到子节点列表
+ */
+ private List getChildList(List list, SysDeptEntity t) {
+ List tList = new ArrayList<>();
+ for (SysDeptEntity n : list) {
+ if (n.getParentId() != null && n.getParentId().longValue() == t.getDeptId().longValue()) {
+ tList.add(n);
+ }
+ }
+ return tList;
+ }
+
+ /**
+ * 判断是否还有子节点
+ */
+ private boolean hasChild(List list, SysDeptEntity t) {
+ return !getChildList(list, t).isEmpty();
+ }
+
+ /**
+ * 根据角色ID查询部门树信息
+ *
+ * @param roleId 角色ID
+ * @return 选中部门列表
+ */
+ @Override
+ public List selectDeptListByRoleId(Long roleId) {
+ SysRoleEntity role = roleMapper.selectRoleById(roleId);
+ return baseMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
+ }
+
+ /**
+ * 查询部门树结构信息
+ *
+ * @param dept 部门信息
+ * @return 部门树信息集合
+ */
+ @Override
+ public List selectDeptTreeList(SysDeptEntity dept) {
+ List depts = this.selectDeptList(dept);
+ return buildDeptTreeSelect(depts);
+ }
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDictDataServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDictDataServiceImpl.java
new file mode 100644
index 0000000..8a4636e
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDictDataServiceImpl.java
@@ -0,0 +1,113 @@
+package com.starry.admin.modules.system.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.starry.admin.modules.system.entity.SysDictDataEntity;
+import com.starry.admin.modules.system.mapper.SysDictDataMapper;
+import com.starry.admin.modules.system.service.ISysDictDataService;
+import com.starry.admin.modules.system.vo.SysDictDataVo;
+import com.starry.admin.utils.DictUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 字典数据表Service业务层处理
+ *
+ * @author admin
+ */
+@Service
+public class SysDictDataServiceImpl extends ServiceImpl implements ISysDictDataService {
+ @Resource
+ private SysDictDataMapper sysDictDataMapper;
+
+ /**
+ * 查询字典数据表
+ *
+ * @param dictDataId 字典数据表主键
+ * @return 字典数据表
+ */
+ @Override
+ public SysDictDataEntity selectXlDictDataByDictDataId(Long dictDataId) {
+ return sysDictDataMapper.selectXlDictDataByDictDataId(dictDataId);
+ }
+
+ /**
+ * 查询字典数据表列表
+ *
+ * @param sysDictDataEntity 字典数据表
+ * @return 字典数据表
+ */
+ @Override
+ public IPage selectXlDictDataList(SysDictDataVo sysDictDataEntity) {
+ return sysDictDataMapper.selectXlDictDataList(new Page<>(sysDictDataEntity.getPageNum(), sysDictDataEntity.getPageSize()), sysDictDataEntity);
+ }
+
+ /**
+ * 新增字典数据表
+ *
+ * @param sysDictDataEntity 字典数据表
+ * @return 结果
+ */
+ @Override
+ public boolean create(SysDictDataEntity sysDictDataEntity) {
+ return save(sysDictDataEntity);
+ }
+
+ /**
+ * 修改字典数据表
+ *
+ * @param sysDictDataEntity 字典数据表
+ * @return 结果
+ */
+ @Override
+ public boolean update(SysDictDataEntity sysDictDataEntity) {
+ return updateById(sysDictDataEntity);
+ }
+
+ /**
+ * 批量删除字典数据表
+ *
+ * @param dictDataIds 需要删除的字典数据表主键
+ * @return 结果
+ */
+ @Override
+ public int deleteXlDictDataByDictDataIds(Long[] dictDataIds) {
+ return sysDictDataMapper.deleteBatchIds(Arrays.asList(dictDataIds));
+ }
+
+ /**
+ * 删除字典数据表信息
+ *
+ * @param dictDataId 字典数据表主键
+ * @return 结果
+ */
+ @Override
+ public int deleteXlDictDataByDictDataId(Long dictDataId) {
+ return sysDictDataMapper.deleteById(dictDataId);
+ }
+
+ /**
+ * 根据字典类型查询字典数据
+ *
+ * @param dictType 字典类型
+ * @return 字典数据集合信息
+ */
+ @Override
+ public List selectDictDataByType(String dictType) {
+ List dictDataList = DictUtils.getDictCache(dictType);
+ if (CollectionUtil.isNotEmpty(dictDataList)) {
+ return dictDataList;
+ }
+ dictDataList = sysDictDataMapper.selectDictDataByType(dictType);
+ if (CollectionUtil.isNotEmpty(dictDataList)) {
+ DictUtils.setDictCache(dictType, dictDataList);
+ return dictDataList;
+ }
+ return null;
+ }
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDictServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDictServiceImpl.java
new file mode 100644
index 0000000..9c0c0e0
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysDictServiceImpl.java
@@ -0,0 +1,138 @@
+package com.starry.admin.modules.system.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.starry.admin.modules.system.entity.SysDictDataEntity;
+import com.starry.admin.modules.system.entity.SysDictEntity;
+import com.starry.admin.modules.system.mapper.SysDictDataMapper;
+import com.starry.admin.modules.system.mapper.SysDictMapper;
+import com.starry.admin.modules.system.service.ISysDictService;
+import com.starry.admin.modules.system.vo.SysDictDataVo;
+import com.starry.admin.modules.system.vo.SysDictVo;
+import com.starry.admin.utils.DictUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 字典表Service业务层处理
+ *
+ * @author admin
+ */
+@Service
+public class SysDictServiceImpl extends ServiceImpl implements ISysDictService {
+ @Resource
+ private SysDictMapper sysDictMapper;
+ @Resource
+ private SysDictDataMapper sysDictDataMapper;
+
+ /**
+ * 查询字典表
+ *
+ * @param dictId 字典表主键
+ * @return 字典表
+ */
+ @Override
+ public SysDictEntity selectXlDictByDictId(Long dictId) {
+ return sysDictMapper.selectXlDictByDictId(dictId);
+ }
+
+ /**
+ * 查询字典表列表
+ *
+ * @param sysDictVo 字典表
+ * @return 字典表
+ */
+ @Override
+ public Page selectXlDictList(SysDictVo sysDictVo) {
+ return sysDictMapper.selectXlDictList(new Page<>(sysDictVo.getPageNum(), sysDictVo.getPageSize()), sysDictVo);
+ }
+
+ /**
+ * 新增字典表
+ *
+ * @param sysDictEntity 字典表
+ * @return 结果
+ */
+ @Override
+ public boolean create(SysDictEntity sysDictEntity) {
+ return save(sysDictEntity);
+ }
+
+ /**
+ * 修改字典表
+ *
+ * @param sysDictEntity 字典表
+ * @return 结果
+ */
+ @Override
+ public boolean update(SysDictEntity sysDictEntity) {
+ return updateById(sysDictEntity);
+ }
+
+ /**
+ * 批量删除字典表
+ *
+ * @param dictIds 需要删除的字典表主键
+ * @return 结果
+ */
+ @Override
+ public int deleteXlDictByDictIds(Long[] dictIds) {
+ return sysDictMapper.deleteBatchIds(Arrays.asList(dictIds));
+ }
+
+ /**
+ * 删除字典表信息
+ *
+ * @param dictId 字典表主键
+ * @return 结果
+ */
+ @Override
+ public int deleteXlDictByDictId(Long dictId) {
+ return sysDictMapper.deleteById(dictId);
+ }
+
+ @Override
+ public List selectDictTypeAll() {
+ return sysDictMapper.selectList(new LambdaQueryWrapper<>());
+ }
+
+ /**
+ * 加载字典缓存数据
+ */
+ @Override
+ public void loadingDictCache() {
+ SysDictDataVo dictData = new SysDictDataVo();
+ dictData.setStatus(0);
+ // 按字典编码分组,不分页,size < 0
+ IPage iPage = sysDictDataMapper.selectXlDictDataList(new Page<>(1, -1), dictData);
+ Map> dictDataMap = iPage.getRecords().stream().collect(Collectors.groupingBy(SysDictDataEntity::getDictType));
+ for (Map.Entry> entry : dictDataMap.entrySet()) {
+ DictUtils.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(SysDictDataEntity::getSort)).collect(Collectors.toList()));
+ }
+ }
+
+ /**
+ * 清空字典缓存数据
+ */
+ @Override
+ public void clearDictCache() {
+ DictUtils.clearDictCache();
+ }
+
+ /**
+ * 重置字典缓存数据
+ */
+ @Override
+ public void resetDictCache() {
+ clearDictCache();
+ loadingDictCache();
+ }
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysLoginLogServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysLoginLogServiceImpl.java
new file mode 100644
index 0000000..2ee35b5
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysLoginLogServiceImpl.java
@@ -0,0 +1,95 @@
+package com.starry.admin.modules.system.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.starry.admin.modules.system.entity.SysLoginLogEntity;
+import com.starry.admin.modules.system.entity.SysLoginLogVo;
+import com.starry.admin.modules.system.mapper.SysLoginLogMapper;
+import com.starry.admin.modules.system.service.ISysLoginLogService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Arrays;
+
+/**
+ * 系统访问日志表Service业务层处理
+ *
+ * @author admin
+ */
+@Service
+public class SysLoginLogServiceImpl extends ServiceImpl implements ISysLoginLogService {
+ @Resource
+ private SysLoginLogMapper xlLoginLogMapper;
+
+ /**
+ * 查询系统访问日志表
+ *
+ * @param loginId 系统访问日志表主键
+ * @return 系统访问日志表
+ */
+ @Override
+ public SysLoginLogEntity selectXlLoginLogByLoginId(Long loginId) {
+ return xlLoginLogMapper.selectXlLoginLogByLoginId(loginId);
+ }
+
+ /**
+ * 查询系统访问日志表列表
+ *
+ * @param vo 系统访问日志表
+ * @return 系统访问日志表
+ */
+ @Override
+ public IPage selectXlLoginLogList(SysLoginLogVo vo) {
+ return xlLoginLogMapper.selectXlLoginLogList(new Page<>(vo.getPageNum(), vo.getPageSize()), vo);
+ }
+
+ /**
+ * 新增系统访问日志表
+ *
+ * @param sysLoginLogEntity 系统访问日志表
+ * @return 结果
+ */
+ @Override
+ public boolean create(SysLoginLogEntity sysLoginLogEntity) {
+ return save(sysLoginLogEntity);
+ }
+
+ /**
+ * 修改系统访问日志表
+ *
+ * @param sysLoginLogEntity 系统访问日志表
+ * @return 结果
+ */
+ @Override
+ public boolean update(SysLoginLogEntity sysLoginLogEntity) {
+ return updateById(sysLoginLogEntity);
+ }
+
+ /**
+ * 批量删除系统访问日志表
+ *
+ * @param loginIds 需要删除的系统访问日志表主键
+ * @return 结果
+ */
+ @Override
+ public int deleteXlLoginLogByLoginIds(Long[] loginIds) {
+ return xlLoginLogMapper.deleteBatchIds(Arrays.asList(loginIds));
+ }
+
+ /**
+ * 删除系统访问日志表信息
+ *
+ * @param loginId 系统访问日志表主键
+ * @return 结果
+ */
+ @Override
+ public int deleteXlLoginLogByLoginId(Long loginId) {
+ return xlLoginLogMapper.deleteById(loginId);
+ }
+
+ @Override
+ public void cleanLoginlog() {
+ xlLoginLogMapper.cleanLoginlog();
+ }
+}
diff --git a/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysMenuServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysMenuServiceImpl.java
new file mode 100644
index 0000000..f815f2d
--- /dev/null
+++ b/play-admin/src/main/java/com/starry/admin/modules/system/service/impl/SysMenuServiceImpl.java
@@ -0,0 +1,331 @@
+package com.starry.admin.modules.system.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.starry.admin.common.domain.TreeSelect;
+import com.starry.admin.modules.system.entity.SysMenuEntity;
+import com.starry.admin.modules.system.entity.SysRoleEntity;
+import com.starry.admin.modules.system.mapper.SysMenuMapper;
+import com.starry.admin.modules.system.mapper.SysRoleMapper;
+import com.starry.admin.modules.system.service.SysMenuService;
+import com.starry.admin.modules.system.vo.MetaVo;
+import com.starry.admin.modules.system.vo.RouterVo;
+import com.starry.admin.modules.system.vo.SimpleMenu;
+import com.starry.admin.utils.SecurityUtils;
+import com.starry.common.constant.Constants;
+import com.starry.common.constant.UserConstants;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * 菜单表 服务实现类
+ *
+ *
+ * @author admin
+ * @since 2022-07-03
+ */
+@Service
+public class SysMenuServiceImpl extends ServiceImpl implements SysMenuService {
+
+ @Resource
+ private SysRoleMapper roleMapper;
+
+ @Override
+ public boolean create(SysMenuEntity menu) {
+ return save(menu);
+ }
+
+
+ @Override
+ public Page listPage(SysMenuEntity menu, String userId, Integer pageSize, Integer pageNum) {
+ Page page = new Page<>(pageNum, pageSize);
+ // 超级管理员显示所有菜单信息
+ if (SecurityUtils.isAdmin(userId)) {
+ return baseMapper.selectPage(page, new LambdaQueryWrapper().eq(SysMenuEntity::getStatus, 1));
+ } else {
+ List menuList = baseMapper.selectMenuListByUserId(menu, userId, page);
+ return page.setRecords(menuList);
+ }
+ }
+
+ @Override
+ public List selectMenuList(SysMenuEntity menu, String userId) {
+ List menuList;
+ // 超级管理员显示所有菜单信息
+ if (SecurityUtils.isAdmin(userId)) {
+ menuList = baseMapper.selectMenuList(menu);
+ } else {
+ menuList = baseMapper.selectMenuListByUserId(menu, userId);
+ }
+ return menuList;
+ }
+
+ @Override
+ public List selectMenuList(String userId) {
+ return selectMenuList(new SysMenuEntity(), userId);
+ }
+
+ @Override
+ public String checkMenuNameUnique(SysMenuEntity menu) {
+ long menuId = menu.getMenuId() == null ? -1L : menu.getMenuId();
+ List menus = baseMapper.selectList(new LambdaQueryWrapper()
+ .eq(SysMenuEntity::getMenuName, menu.getMenuName())
+ .eq(SysMenuEntity::getParentId, menu.getParentId()));
+ if (CollectionUtil.isNotEmpty(menus) && menus.get(0).getMenuId() != menuId) {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ @Override
+ public boolean hasChildByMenuId(Long menuId) {
+ Long result = baseMapper.selectCount(new LambdaQueryWrapper().eq(SysMenuEntity::getParentId, menuId));
+ return result > 0;
+ }
+
+ @Override
+ public List buildMenuTreeSelect(List menus) {
+ List returnList = new ArrayList<>();
+ List tempList = new ArrayList<>();
+ for (SysMenuEntity menu : menus) {
+ tempList.add(menu.getMenuId());
+ }
+ for (SysMenuEntity menu : menus) {
+ // 如果是顶级节点,遍历该父节点所有的子节点
+ if (!tempList.contains(menu.getParentId())) {
+ recursionList(menus, menu);
+ returnList.add(menu);
+ }
+ }
+ if (CollectionUtil.isEmpty(returnList)) {
+ returnList = menus;
+ }
+ return returnList.stream().map(TreeSelect::new).collect(Collectors.toList());
+ }
+
+ @Override
+ public SysMenuEntity selectMenuById(Long menuId) {
+ return baseMapper.selectById(menuId);
+ }
+
+ @Override
+ public List selectMenuListByRoleId(Long roleId) {
+ SysRoleEntity role = roleMapper.selectRoleById(roleId);
+ return baseMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
+ }
+
+ @Override
+ public Set selectMenuPermsByUserId(String userId) {
+ // 获取菜单权限集合
+ List perms = baseMapper.selectMenuPermsByUserId(userId);
+ Set permsSet = new HashSet<>();
+ for (String perm : perms) {
+ if (StrUtil.isNotEmpty(perm)) {
+ permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+ }
+ }
+ return permsSet;
+ }
+
+ @Override
+ public List