SysDeptService.java 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package cc.uncarbon.module.sys.service;
  2. import cc.uncarbon.framework.core.constant.HelioConstant;
  3. import cc.uncarbon.framework.core.context.UserContextHolder;
  4. import cc.uncarbon.framework.core.exception.BusinessException;
  5. import cc.uncarbon.module.sys.constant.SysConstant;
  6. import cc.uncarbon.module.sys.entity.SysDeptEntity;
  7. import cc.uncarbon.module.sys.enums.SysErrorEnum;
  8. import cc.uncarbon.module.sys.mapper.SysDeptMapper;
  9. import cc.uncarbon.module.sys.model.interior.UserDeptContainer;
  10. import cc.uncarbon.module.sys.model.interior.UserRoleContainer;
  11. import cc.uncarbon.module.sys.model.request.AdminInsertOrUpdateSysDeptDTO;
  12. import cc.uncarbon.module.sys.model.response.SysDeptBO;
  13. import cn.hutool.core.bean.BeanUtil;
  14. import cn.hutool.core.collection.CollUtil;
  15. import cn.hutool.core.util.ObjectUtil;
  16. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  17. import lombok.RequiredArgsConstructor;
  18. import lombok.extern.slf4j.Slf4j;
  19. import org.springframework.stereotype.Service;
  20. import org.springframework.transaction.annotation.Transactional;
  21. import java.util.*;
  22. import java.util.stream.Collectors;
  23. /**
  24. * 部门
  25. */
  26. @RequiredArgsConstructor
  27. @Service
  28. @Slf4j
  29. public class SysDeptService {
  30. private final SysDeptMapper sysDeptMapper;
  31. private final SysUserDeptRelationService sysUserDeptRelationService;
  32. private final SysRoleService sysRoleService;
  33. /**
  34. * 后台管理-列表
  35. */
  36. public List<SysDeptBO> adminList() {
  37. return entityList2BOs(sysDeptMapper.sortedList());
  38. }
  39. /**
  40. * 根据 ID 取详情
  41. *
  42. * @param id 主键ID
  43. * @return null or BO
  44. */
  45. public SysDeptBO getOneById(Long id) {
  46. return this.getOneById(id, false);
  47. }
  48. /**
  49. * 根据 ID 取详情
  50. *
  51. * @param id 主键ID
  52. * @param throwIfInvalidId 是否在 ID 无效时抛出异常
  53. * @return null or BO
  54. */
  55. public SysDeptBO getOneById(Long id, boolean throwIfInvalidId) throws BusinessException {
  56. SysDeptEntity entity = sysDeptMapper.selectById(id);
  57. if (throwIfInvalidId) {
  58. SysErrorEnum.INVALID_ID.assertNotNull(entity);
  59. }
  60. return this.entity2BO(entity);
  61. }
  62. /**
  63. * 后台管理-新增
  64. */
  65. @Transactional(rollbackFor = Exception.class)
  66. public Long adminInsert(AdminInsertOrUpdateSysDeptDTO dto) {
  67. log.info("[后台管理-新增部门] >> 入参={}", dto);
  68. this.checkExistence(dto);
  69. if (ObjectUtil.isNull(dto.getParentId())) {
  70. dto.setParentId(SysConstant.ROOT_PARENT_ID);
  71. }
  72. dto.setId(null);
  73. SysDeptEntity entity = new SysDeptEntity();
  74. BeanUtil.copyProperties(dto, entity);
  75. sysDeptMapper.insert(entity);
  76. return entity.getId();
  77. }
  78. /**
  79. * 后台管理-编辑
  80. */
  81. @Transactional(rollbackFor = Exception.class)
  82. public void adminUpdate(AdminInsertOrUpdateSysDeptDTO dto) {
  83. log.info("[后台管理-编辑部门] >> 入参={}", dto);
  84. this.checkExistence(dto);
  85. if (ObjectUtil.isNull(dto.getParentId())) {
  86. dto.setParentId(SysConstant.ROOT_PARENT_ID);
  87. }
  88. SysDeptEntity entity = new SysDeptEntity();
  89. BeanUtil.copyProperties(dto, entity);
  90. sysDeptMapper.updateById(entity);
  91. }
  92. /**
  93. * 后台管理-删除
  94. */
  95. @Transactional(rollbackFor = Exception.class)
  96. public void adminDelete(Collection<Long> ids) {
  97. log.info("[后台管理-删除部门] >> 入参={}", ids);
  98. sysDeptMapper.deleteByIds(ids);
  99. }
  100. /**
  101. * 后台管理-下拉框数据
  102. * @param inferiorsOnly 只能看到本部门及以下
  103. */
  104. public List<SysDeptBO> adminSelectOptions(boolean inferiorsOnly) {
  105. if (inferiorsOnly) {
  106. UserRoleContainer currentUser = sysRoleService.getCurrentUserRoleContainer();
  107. if (currentUser.isNotAnyAdmin()) {
  108. // 非管理员才会限制,只能看到本部门及以下
  109. UserDeptContainer deptContainer = getCurrentUserDeptContainer(true);
  110. return entityList2BOs(deptContainer.getVisibleDepts());
  111. }
  112. }
  113. // 能看所有
  114. return adminList();
  115. }
  116. /**
  117. * 取当前用户关联部门信息
  118. * 仅内部使用
  119. * @param queryVisibleDept 是否要进一步查询可见部门
  120. */
  121. protected UserDeptContainer getCurrentUserDeptContainer(boolean queryVisibleDept) {
  122. return getSpecifiedUserDeptContainer(UserContextHolder.getUserId(), queryVisibleDept);
  123. }
  124. /**
  125. * 取指定用户关联部门信息
  126. * 仅内部使用
  127. * @param queryVisibleDept 是否要进一步查询可见部门
  128. */
  129. protected UserDeptContainer getSpecifiedUserDeptContainer(Long specifiedUserId, boolean queryVisibleDept) {
  130. List<Long> currentUserDeptIds = sysUserDeptRelationService.getUserDeptIds(specifiedUserId);
  131. List<SysDeptEntity> currentUserDepts = Collections.emptyList();
  132. if (CollUtil.isNotEmpty(currentUserDeptIds)) {
  133. currentUserDepts = sysDeptMapper.selectBatchIds(currentUserDeptIds);
  134. }
  135. UserDeptContainer container = new UserDeptContainer(currentUserDeptIds, currentUserDepts);
  136. if (queryVisibleDept && container.hasRelatedDepts()) {
  137. List<SysDeptEntity> allDepts = sysDeptMapper.sortedList();
  138. List<SysDeptEntity> inferiors = determineAllInferiors(allDepts, container.primaryRelatedDept());
  139. container.updateVisibleDepts(inferiors);
  140. }
  141. return container;
  142. }
  143. /*
  144. ----------------------------------------------------------------
  145. 私有方法 private methods
  146. ----------------------------------------------------------------
  147. */
  148. /**
  149. * 实体转 BO
  150. *
  151. * @param entity 实体
  152. * @return BO
  153. */
  154. private SysDeptBO entity2BO(SysDeptEntity entity) {
  155. if (entity == null) {
  156. return null;
  157. }
  158. SysDeptBO bo = new SysDeptBO();
  159. BeanUtil.copyProperties(entity, bo);
  160. // 可以在此处为BO填充字段
  161. if (SysConstant.ROOT_PARENT_ID.equals(bo.getParentId())) {
  162. // 返回前端时,不显示 parentId = 0
  163. bo.setParentId(null);
  164. }
  165. return bo;
  166. }
  167. /**
  168. * 实体 List 转 BO List
  169. *
  170. * @param entityList 实体 List
  171. * @return BO List
  172. */
  173. private List<SysDeptBO> entityList2BOs(List<SysDeptEntity> entityList) {
  174. if (CollUtil.isEmpty(entityList)) {
  175. return Collections.emptyList();
  176. }
  177. // 深拷贝
  178. List<SysDeptBO> ret = new ArrayList<>(entityList.size());
  179. entityList.forEach(
  180. entity -> ret.add(this.entity2BO(entity))
  181. );
  182. return ret;
  183. }
  184. /**
  185. * 检查是否已存在相同数据
  186. *
  187. * @param dto DTO
  188. */
  189. private void checkExistence(AdminInsertOrUpdateSysDeptDTO dto) {
  190. SysDeptEntity existingEntity = sysDeptMapper.selectOne(
  191. new QueryWrapper<SysDeptEntity>()
  192. .lambda()
  193. // 仅取主键ID
  194. .select(SysDeptEntity::getId)
  195. // 名称相同
  196. .eq(SysDeptEntity::getTitle, dto.getTitle())
  197. .last(HelioConstant.CRUD.SQL_LIMIT_1)
  198. );
  199. if (existingEntity != null && !existingEntity.getId().equals(dto.getId())) {
  200. throw new BusinessException(400, "已存在相同部门,请重新输入");
  201. }
  202. }
  203. /**
  204. * 找出本部门及所有下级部门
  205. *
  206. * @param start 本部门
  207. * @return 本部门 + 所有下级部门
  208. */
  209. private List<SysDeptEntity> determineAllInferiors(List<SysDeptEntity> entityList, SysDeptEntity start) {
  210. // 结果集合
  211. List<SysDeptEntity> ret = new ArrayList<>(entityList.size());
  212. Deque<SysDeptEntity> deque = new ArrayDeque<>();
  213. // 转map提高效率
  214. Map<Long, List<SysDeptEntity>> groupByParentId = entityList.stream().collect(Collectors.groupingBy(SysDeptEntity::getParentId));
  215. // 起点
  216. ret.add(start);
  217. deque.add(start);
  218. // 循环填充下级部门实例
  219. while (CollUtil.isNotEmpty(deque)) {
  220. SysDeptEntity parent = deque.pop();
  221. List<SysDeptEntity> children = groupByParentId.get(parent.getId());
  222. if (CollUtil.isNotEmpty(children)) {
  223. ret.addAll(children);
  224. deque.addAll(children);
  225. }
  226. }
  227. return ret;
  228. }
  229. }