|
|
@@ -3,6 +3,7 @@ package cn.reghao.devops.web.account.service.impl;
|
|
|
import cn.reghao.devops.web.account.db.repository.MenuRepository;
|
|
|
import cn.reghao.devops.web.account.db.repository.RoleRepository;
|
|
|
import cn.reghao.devops.web.account.model.constant.MenuType;
|
|
|
+import cn.reghao.devops.web.account.model.vo.MenuTree;
|
|
|
import cn.reghao.devops.web.account.service.MenuService;
|
|
|
import cn.reghao.jutil.jdk.result.Result;
|
|
|
import cn.reghao.jutil.jdk.result.ResultStatus;
|
|
|
@@ -11,8 +12,8 @@ import cn.reghao.devops.web.account.model.po.Menu;
|
|
|
import cn.reghao.devops.web.account.model.po.Role;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
-import java.time.LocalDateTime;
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@@ -33,23 +34,50 @@ public class MenuServiceImpl implements MenuService {
|
|
|
|
|
|
@Override
|
|
|
public synchronized Result addMenu(Menu menu) {
|
|
|
- Result result = moreThanTwoParents(menu.getPid());
|
|
|
+ int pid = menu.getPid();
|
|
|
+ int total = menuRepository.countByPid(pid);
|
|
|
+ if (total >= 100) {
|
|
|
+ return Result.result(ResultStatus.FAIL, "每个 dir 最多可包含 100 个 page");
|
|
|
+ }
|
|
|
+
|
|
|
+ Result result = moreThanTwoParents(pid);
|
|
|
if (result.getCode() != ResultStatus.SUCCESS.getCode()) {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- // 调整 menu 组内元素的位置
|
|
|
- insertNewMenu(menu);
|
|
|
- menu.setEnabled(true);
|
|
|
- Menu menuEntity = menuRepository.save(menu);
|
|
|
+ String type = menu.getType();
|
|
|
+ if (type.equals(MenuType.dir.name())) {
|
|
|
+ menu.setUrl("#");
|
|
|
+ } else {
|
|
|
+ String url = menu.getUrl();
|
|
|
+ Result result1 = checkUrl(url);
|
|
|
+ if (result1.getCode() != ResultStatus.SUCCESS.getCode()) {
|
|
|
+ return result1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Menu> siblings = menuRepository.findByPid(menu.getPid());
|
|
|
+ if (siblings.isEmpty()) {
|
|
|
+ menu.setPos(1);
|
|
|
+ } else {
|
|
|
+ siblings.sort(Comparator.comparingInt(Menu::getPos));
|
|
|
+ int max = siblings.get(siblings.size()-1).getPos();
|
|
|
+ menu.setPos(max+1);
|
|
|
+ }
|
|
|
|
|
|
- //Set<Role> roles = menu.getRoles();
|
|
|
- Set<Role> roles = Collections.emptySet();
|
|
|
- roles.forEach(role -> role.getMenus().add(menuEntity));
|
|
|
- roleRepository.saveAll(new ArrayList<>(roles));
|
|
|
+ menuRepository.save(menu);
|
|
|
return Result.result(ResultStatus.SUCCESS);
|
|
|
}
|
|
|
|
|
|
+ private Result checkUrl(String url) {
|
|
|
+ Menu menu1 = menuRepository.findByUrl(url);
|
|
|
+ if (menu1 != null) {
|
|
|
+ return Result.result(ResultStatus.FAIL, String.format("url 为 %s 的 Menu 已存在", url));
|
|
|
+ }
|
|
|
+
|
|
|
+ return Result.success();
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 检查菜单的层级, Menu 最多只能有两个 parent, 即最多只能有三级菜单
|
|
|
*
|
|
|
@@ -73,151 +101,46 @@ public class MenuServiceImpl implements MenuService {
|
|
|
return Result.result(ResultStatus.SUCCESS);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 向 menu 组插入元素时调整组内 menu 的位置
|
|
|
- *
|
|
|
- * @date 2021-05-18 上午9:54
|
|
|
- */
|
|
|
- private void insertNewMenu(Menu menu) {
|
|
|
- int pid = menu.getPid();
|
|
|
- if (pid != 0) {
|
|
|
- Menu pMenu = menuRepository.getOne(pid);
|
|
|
- if (pMenu.getType().equals(MenuType.page.name())) {
|
|
|
- log.error("父级菜单的类型不能是 PAGE");
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- List<Menu> menus = menuRepository.findByPid(pid);
|
|
|
- menus.sort(Comparator.comparingInt(Menu::getPos));
|
|
|
- // 组内没有 menu 或新增的 menu 在组内排在最后一位
|
|
|
- if (menus.isEmpty()) {
|
|
|
- menu.setPos(1);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // menu 的新位置
|
|
|
- int pos = menu.getPos()+1;
|
|
|
- int size = menus.size();
|
|
|
- if (pos == 1) {
|
|
|
- // menu 的位置在 menu 组的首位, 组内的其他元素位置向后移一位
|
|
|
- menu.setPos(1);
|
|
|
- moveBackward(menus, 1);
|
|
|
- } else if (pos >= size+1) {
|
|
|
- // menu 的位置在 menu 组的末尾, 组内的其他元素位置不变
|
|
|
- menu.setPos(size+1);
|
|
|
- } else {
|
|
|
- // menu 的位置在 menu 组的中间, pos 开始的元素位置向后移一位
|
|
|
- menu.setPos(pos);
|
|
|
- moveBackward(menus, pos);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 向后移动元素(向 menu 组新增元素时调用)
|
|
|
- *
|
|
|
- * @return
|
|
|
- * @date 2021-07-15 下午5:07
|
|
|
- */
|
|
|
- private void moveBackward(List<Menu> menus, int startPos) {
|
|
|
- for (int i = startPos-1; i < menus.size(); i++) {
|
|
|
- Menu tmpMenu = menus.get(i);
|
|
|
- int newPos = tmpMenu.getPos()+1;
|
|
|
- tmpMenu.setPos(newPos);
|
|
|
- }
|
|
|
- menuRepository.saveAll(menus);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 向前移动元素(从 menu 组删除元素时调用)
|
|
|
- *
|
|
|
- * @param
|
|
|
- * @return
|
|
|
- * @date 2021-07-15 下午5:41
|
|
|
- */
|
|
|
- private void moveForward(List<Menu> menus, int startPos) {
|
|
|
- for (int i = startPos; i < menus.size(); i++) {
|
|
|
- Menu tmpMenu = menus.get(i);
|
|
|
- int newPos = tmpMenu.getPos()-1;
|
|
|
- tmpMenu.setPos(newPos);
|
|
|
- }
|
|
|
- menuRepository.saveAll(menus);
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public synchronized Result updateMenu(MenuDto menuDto) {
|
|
|
int menuId = menuDto.getMenuId();
|
|
|
- Menu menuEntity = menuRepository.getOne(menuId);
|
|
|
+ Menu menuEntity = menuRepository.findById(menuId).orElse(null);
|
|
|
if (menuEntity == null) {
|
|
|
return Result.result(ResultStatus.FAIL, String.format("ID 为 %s 的 Menu 不存在", menuId));
|
|
|
}
|
|
|
|
|
|
- int oldPos = menuEntity.getPos();
|
|
|
- // menu 的新位置
|
|
|
- int newPos = menuDto.getPos()+1;
|
|
|
- int pid = menuDto.getPid();
|
|
|
- if (pid != menuEntity.getPid()) {
|
|
|
- Result result = moreThanTwoParents(pid);
|
|
|
- if (result.getCode() != ResultStatus.SUCCESS.getCode()) {
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- // menu 更换到了新的 menu 组
|
|
|
- menuEntity.setPid(pid);
|
|
|
- menuEntity.setPos(menuDto.getPos());
|
|
|
- insertNewMenu(menuEntity);
|
|
|
- } else if (newPos != oldPos) {
|
|
|
- reOrderMenus(pid, oldPos, newPos);
|
|
|
- menuEntity.setPos(newPos);
|
|
|
+ String url = menuDto.getUrl();
|
|
|
+ Result result1 = checkUrl(url);
|
|
|
+ if (result1.getCode() != ResultStatus.SUCCESS.getCode()) {
|
|
|
+ return result1;
|
|
|
}
|
|
|
|
|
|
menuEntity.setName(menuDto.getName());
|
|
|
menuEntity.setUrl(menuDto.getUrl());
|
|
|
menuEntity.setIcon(menuDto.getIcon());
|
|
|
- menuEntity.setUpdateTime(LocalDateTime.now());
|
|
|
menuRepository.save(menuEntity);
|
|
|
-
|
|
|
- Set<Role> roles = menuDto.getRoles();
|
|
|
- roles.forEach(role -> role.getMenus().add(menuEntity));
|
|
|
- roleRepository.saveAll(new ArrayList<>(roles));
|
|
|
return Result.result(ResultStatus.SUCCESS);
|
|
|
}
|
|
|
|
|
|
- public void updateMenusStatus(boolean status, List<Integer> menuIds) {
|
|
|
- menuRepository.findAllById(menuIds).forEach(menu -> {
|
|
|
- menu.setEnabled(status);
|
|
|
- menuRepository.save(menu);
|
|
|
- });
|
|
|
- }
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ @Override
|
|
|
+ public synchronized Result deleteMenu(Integer menuId) {
|
|
|
+ Menu menu = menuRepository.findById(menuId).orElse(null);
|
|
|
+ if (menu == null) {
|
|
|
+ return Result.result(ResultStatus.FAIL, String.format("ID 为 %s 的 Menu 不存在", menuId));
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 对组内的菜单进行重排序,只需调整 oldPos~newPos 之间的元素位置
|
|
|
- *
|
|
|
- * @param
|
|
|
- * @return
|
|
|
- * @date 2021-07-21 上午11:07
|
|
|
- */
|
|
|
- private void reOrderMenus(int pid, int oldPos, int newPos) {
|
|
|
- Map<Integer, Menu> map = menuRepository.findByPid(pid).stream()
|
|
|
- .collect(Collectors.toMap(Menu::getPos, menu -> menu));
|
|
|
- map.remove(oldPos);
|
|
|
- if (newPos < oldPos) {
|
|
|
- // 向前移动
|
|
|
- for (int i = newPos, j = 1; i < oldPos; i++, j++) {
|
|
|
- map.get(i).setPos(newPos+j);
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 向后移动
|
|
|
- for (int i = newPos-1, j = 1; i > oldPos; i--, j++) {
|
|
|
- map.get(i).setPos(newPos-j);
|
|
|
+ String type = menu.getType();
|
|
|
+ if (type.equals(MenuType.dir.name())) {
|
|
|
+ List<Menu> list1 = menuRepository.findByPid(menu.getId());
|
|
|
+ Map<String, List<Menu>> map = list1.stream().collect(Collectors.groupingBy(Menu::getType));
|
|
|
+ List<Menu> dirMenus = map.get(MenuType.dir.name());
|
|
|
+ if (!dirMenus.isEmpty()) {
|
|
|
+ for (Menu menu1 : dirMenus) {
|
|
|
+ List<Menu> list2 = menuRepository.findByPid(menu1.getId());
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- menuRepository.saveAll(new ArrayList<>(map.values()));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public synchronized Result deleteMenu(Integer menuId) {
|
|
|
- Menu menu = menuRepository.getOne(menuId);
|
|
|
|
|
|
// 删除 Role 关联的 Menu
|
|
|
for (Role role : menu.getRoles()) {
|
|
|
@@ -225,41 +148,59 @@ public class MenuServiceImpl implements MenuService {
|
|
|
roleRepository.save(role);
|
|
|
}
|
|
|
|
|
|
- // 重新调整组内排序
|
|
|
- int pid = menu.getPid();
|
|
|
- List<Menu> menus = menuRepository.findByPid(pid);
|
|
|
- menus.sort(Comparator.comparingInt(Menu::getPos));
|
|
|
- int pos = menu.getPos();
|
|
|
- moveForward(menus, pos);
|
|
|
menuRepository.delete(menu);
|
|
|
return Result.result(ResultStatus.SUCCESS);
|
|
|
}
|
|
|
|
|
|
+ private void deleteRoleMenus(Menu menu) {
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
- public Menu getById(Integer menuId) {
|
|
|
- return menuRepository.findById(menuId).orElse(null);
|
|
|
+ public List<MenuTree> getMenusByStatus(Boolean isEnabled) {
|
|
|
+ List<Menu> menuList = menuRepository.findByEnabled(isEnabled);
|
|
|
+ return getSortedZTree(menuList, null);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public List<Menu> getAllMenus() {
|
|
|
- return menuRepository.findAll();
|
|
|
+ public List<MenuTree> getMenusByRole(Role role) {
|
|
|
+ List<Menu> allMenus = menuRepository.findAll();
|
|
|
+ return getSortedZTree(allMenus, role);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public List<Menu> getSortedMenusByStatus(Boolean isEnabled) {
|
|
|
- List<Menu> menuList = menuRepository.findByEnabled(isEnabled);
|
|
|
- Map<Integer, List<Menu>> map = menuList.stream().collect(Collectors.groupingBy(Menu::getPid));
|
|
|
- List<Menu> list = new ArrayList<>();
|
|
|
+ public List<MenuTree> getParentMenus() {
|
|
|
+ List<Menu> allMenus = menuRepository.findByTypeAndEnabledIsTrue(MenuType.dir.name());
|
|
|
+ return getSortedZTree(allMenus, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<MenuTree> getSortedZTree(List<Menu> list, Role role) {
|
|
|
+ Map<Integer, List<Menu>> map = list.stream().collect(Collectors.groupingBy(Menu::getPid));
|
|
|
+ List<MenuTree> menuTrees = new ArrayList<>();
|
|
|
map.forEach((pid, menus) -> {
|
|
|
- list.addAll(menus.stream()
|
|
|
+ menuTrees.addAll(menus.stream()
|
|
|
.sorted(Comparator.comparing(Menu::getPos))
|
|
|
+ .map(menu -> {
|
|
|
+ MenuTree menuTree = new MenuTree(menu);
|
|
|
+ Set<Role> roles = menu.getRoles();
|
|
|
+ if (roles.contains(role)) {
|
|
|
+ // 对应前端的 checked 复选框
|
|
|
+ menuTree.setGranted(true);
|
|
|
+ }
|
|
|
+ return menuTree;
|
|
|
+ })
|
|
|
.collect(Collectors.toList()));
|
|
|
});
|
|
|
|
|
|
- return list;
|
|
|
+ return menuTrees;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updateMenusStatus(boolean status, List<Integer> menuIds) {
|
|
|
+ menuRepository.findAllById(menuIds).forEach(menu -> {
|
|
|
+ menu.setEnabled(status);
|
|
|
+ menuRepository.save(menu);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
public Map<Integer, String> getSortedChildGroupByPid(int pid) {
|
|
|
List<Menu> menus = menuRepository.findByPid(pid);
|
|
|
menus.sort(Comparator.comparingInt(Menu::getPos));
|