Ver código fonte

优化资源管理的页面和接口

reghao 4 anos atrás
pai
commit
de66433393
24 arquivos alterados com 286 adições e 191 exclusões
  1. 11 0
      dmaster/pom.xml
  2. 2 6
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/constant/AppType.java
  3. 12 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/constant/EnvList.java
  4. 0 15
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/constant/EnvType.java
  5. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/BuildDeployController.java
  6. 4 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/AppConfigPageController.java
  7. 3 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/AppPageController.java
  8. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/crud/config/AppCrudService.java
  9. 26 22
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/controller/ResourceController.java
  10. 9 8
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/controller/ResourcePageController.java
  11. 31 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/db/query/MenuQuery.java
  12. 3 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/MenuType.java
  13. 2 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/UserGender.java
  14. 46 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/dto/MenuDTO.java
  15. 2 16
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/vo/MenuVO.java
  16. 16 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/MenuService.java
  17. 88 70
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/MenuServiceImpl.java
  18. 1 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/RoleServiceImpl.java
  19. 5 5
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/controller/MachinePageController.java
  20. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/po/MachineHost.java
  21. 5 5
      dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/TestController.java
  22. 8 7
      dmaster/src/main/java/cn/reghao/autodop/dmaster/view/thymeleaf/attribute/SelectDictAttrProcessor.java
  23. 1 1
      dmaster/src/main/resources/templates/auth/menu/index.html
  24. 5 18
      pom.xml

+ 11 - 0
dmaster/pom.xml

@@ -28,6 +28,17 @@
             <artifactId>spring-boot-starter-validation</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation-api</artifactId>
+            <version>2.0.1.Final</version>
+        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>

+ 2 - 6
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/constant/AppType.java

@@ -1,15 +1,11 @@
 package cn.reghao.autodop.dmaster.app.constant;
 
 /**
- * 应用类型
+ * 应用类型列表
  *
  * @author reghao
  * @date 2019-10-18 14:31:29
  */
 public enum AppType {
-    maven, dotnetCore, npm, cmake, gradle;
-
-    public String getName() {
-        return this.name();
-    }
+    maven, dotnetCore, npm, cmake, gradle
 }

+ 12 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/constant/EnvList.java

@@ -0,0 +1,12 @@
+package cn.reghao.autodop.dmaster.app.constant;
+
+/**
+ * 环境列表
+ * TODO 动态添加
+ *
+ * @author reghao
+ * @date 2019-10-18 14:31:29
+ */
+public enum EnvList {
+    dev, test, uat, prod
+}

+ 0 - 15
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/constant/EnvType.java

@@ -1,15 +0,0 @@
-package cn.reghao.autodop.dmaster.app.constant;
-
-/**
- * 应用对应的环境
- *
- * @author reghao
- * @date 2019-10-18 14:31:29
- */
-public enum EnvType {
-    dev,test,uat,prod;
-
-    public String getName() {
-        return this.name();
-    }
-}

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/BuildDeployController.java

@@ -20,8 +20,8 @@ import org.springframework.web.bind.annotation.*;
 @RestController
 @RequestMapping("/api/app/bd")
 public class BuildDeployController {
-    private BuildDeployDispatcher buildDeployDispatcher;
-    private AppBuildDeployService buildService;
+    private final BuildDeployDispatcher buildDeployDispatcher;
+    private final AppBuildDeployService buildService;
 
     public BuildDeployController(BuildDeployDispatcher buildDeployDispatcher, AppBuildDeployService buildService) {
         this.buildDeployDispatcher = buildDeployDispatcher;

+ 4 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/AppConfigPageController.java

@@ -2,7 +2,7 @@ package cn.reghao.autodop.dmaster.app.controller.view;
 
 import cn.reghao.autodop.common.dagent.app.deploy.PackType;
 import cn.reghao.autodop.dmaster.app.constant.AppType;
-import cn.reghao.autodop.dmaster.app.constant.EnvType;
+import cn.reghao.autodop.dmaster.app.constant.EnvList;
 import cn.reghao.autodop.dmaster.machine.db.query.MachineQuery;
 import cn.reghao.autodop.dmaster.machine.entity.po.info.MachineInfo;
 import cn.reghao.autodop.dmaster.machine.entity.po.info.NetworkInfo;
@@ -67,7 +67,7 @@ public class AppConfigPageController {
                                 @RequestParam(value = "appName", required = false) String appName,
                                 Model model) {
         if (env == null) {
-            env = EnvType.test.name();
+            env = EnvList.test.name();
         }
 
         if (appName != null) {
@@ -145,8 +145,8 @@ public class AppConfigPageController {
 
     private void setCommon(Model model) {
         List<KeyValue> envs = new ArrayList<>();
-        for (EnvType envType : EnvType.values()) {
-            envs.add(new KeyValue(envType.name(), envType.name()));
+        for (EnvList envList : EnvList.values()) {
+            envs.add(new KeyValue(envList.name(), envList.name()));
         }
 
         List<KeyValue> appTypes = new ArrayList<>();

+ 3 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/AppPageController.java

@@ -1,7 +1,7 @@
 package cn.reghao.autodop.dmaster.app.controller.view;
 
 import cn.reghao.autodop.dmaster.app.constant.AppType;
-import cn.reghao.autodop.dmaster.app.constant.EnvType;
+import cn.reghao.autodop.dmaster.app.constant.EnvList;
 import cn.reghao.autodop.dmaster.app.db.query.AppBuildingQuery;
 import cn.reghao.autodop.dmaster.app.db.query.AppDeployingQuery;
 import cn.reghao.autodop.dmaster.app.db.query.AppRunningQuery;
@@ -62,7 +62,7 @@ public class AppPageController {
                             @RequestParam(value = "appName", required = false) String appName,
                             Model model) {
         if (env == null) {
-            env = EnvType.test.name();
+            env = EnvList.test.name();
         }
 
         if (appName != null) {
@@ -192,7 +192,7 @@ public class AppPageController {
                              @RequestParam(value = "appName", required = false) String appName,
                              Model model) {
         if (env == null) {
-            env = EnvType.test.name();
+            env = EnvList.test.name();
         }
 
         if (appName != null) {

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/crud/config/AppCrudService.java

@@ -3,7 +3,7 @@ package cn.reghao.autodop.dmaster.app.db.crud.config;
 import cn.reghao.autodop.common.result.Result;
 import cn.reghao.autodop.common.result.ResultStatus;
 import cn.reghao.autodop.dmaster.app.constant.AppType;
-import cn.reghao.autodop.dmaster.app.constant.EnvType;
+import cn.reghao.autodop.dmaster.app.constant.EnvList;
 import cn.reghao.autodop.dmaster.app.entity.config.ProjOrchestration;
 import cn.reghao.autodop.dmaster.machine.db.crud.MachineInfoCrudService;
 import cn.reghao.autodop.dmaster.machine.entity.po.info.MachineInfo;
@@ -84,7 +84,7 @@ public class AppCrudService {
     }
 
     private Result checkEnum(AppOrchestration app) {
-        Set<String> envs = Arrays.stream(EnvType.values())
+        Set<String> envs = Arrays.stream(EnvList.values())
                 .map(Enum::name)
                 .collect(Collectors.toSet());
         String env = app.getEnv();

+ 26 - 22
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/controller/ResourceController.java

@@ -1,10 +1,13 @@
 package cn.reghao.autodop.dmaster.auth.controller;
 
+import cn.reghao.autodop.common.result.Result;
+import cn.reghao.autodop.common.result.ResultStatus;
+import cn.reghao.autodop.dmaster.auth.db.query.MenuQuery;
+import cn.reghao.autodop.dmaster.auth.entity.dto.MenuDTO;
 import cn.reghao.autodop.dmaster.auth.entity.po.Menu;
-import cn.reghao.autodop.dmaster.auth.entity.po.Role;
 import cn.reghao.autodop.dmaster.auth.entity.vo.MenuVO;
 import cn.reghao.autodop.dmaster.utils.WebBody;
-import cn.reghao.autodop.dmaster.auth.service.ResourceService;
+import cn.reghao.autodop.dmaster.auth.service.MenuServiceImpl;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.http.MediaType;
@@ -14,6 +17,7 @@ import org.springframework.web.bind.annotation.*;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -23,49 +27,49 @@ import java.util.Set;
 @RequestMapping("/api/auth/menu")
 @RestController
 public class ResourceController {
-    private ResourceService resourceService;
+    private final MenuServiceImpl menuServiceImpl;
+    private final MenuQuery menuQuery;
 
-    public ResourceController(ResourceService resourceService) {
-        this.resourceService = resourceService;
+    public ResourceController(MenuServiceImpl menuServiceImpl, MenuQuery menuQuery) {
+        this.menuServiceImpl = menuServiceImpl;
+        this.menuQuery = menuQuery;
     }
 
     @ApiOperation(value = "添加资源")
     @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
     public String addMenu(@Validated Menu menu) {
-        resourceService.addResource(menu);
-        return WebBody.success();
+        Result result = menuServiceImpl.addMenu(menu);
+        return WebBody.result(result);
     }
 
     @ApiOperation(value = "修改资源")
     @PostMapping(value = "/edit", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String modifyMenu(@Validated MenuVO menu, @RequestParam("roles") Set<Role> roles) {
-        resourceService.updateResource(menu, roles);
-        return WebBody.success();
+    public String modifyMenu(@Validated MenuDTO menuDTO) {
+        Result result = menuServiceImpl.updateMenu(menuDTO);
+        return WebBody.result(Result.result(ResultStatus.SUCCESS));
     }
 
     @ApiOperation(value = "修改资源状态")
     @PostMapping(value = "/status/{isEnabled}", produces = MediaType.APPLICATION_JSON_VALUE)
     public String menuStatus(@PathVariable("isEnabled") boolean isEnabled, @RequestParam("ids") List<Integer> ids) {
-        if (isEnabled) {
-
-        }
+        // TODO 待实现
         return WebBody.success();
     }
 
     @ApiOperation(value = "删除资源")
     @DeleteMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String deleteMenu(@PathVariable("id") Menu menu) {
-        resourceService.deleteResource(menu);
-        return WebBody.success();
+    public String deleteMenu(@PathVariable("id") Integer menuId) {
+        Result result = menuServiceImpl.deleteMenu(menuId);
+        return WebBody.result(result);
     }
 
     @ApiOperation(value = "获取所有的资源")
     @GetMapping(value = "/{isEnabled}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String list(@PathVariable(value = "isEnabled", required = false) Boolean isEnabled) {
-        if (isEnabled == null) {
-            isEnabled = true;
-        }
-        List<Menu> list = resourceService.getResourceByStatus(isEnabled);
+    public String list(@PathVariable(value = "isEnabled") Boolean isEnabled) {
+        /* TODO 使用 vo 替换 po
+        List<MenuVO> list = menuQuery.getResourceByStatus(isEnabled).stream().map(MenuVO::new)
+                .collect(Collectors.toList());*/
+        List<Menu> list = menuQuery.getResourceByStatus(isEnabled);
         return WebBody.success(list);
     }
 
@@ -73,7 +77,7 @@ public class ResourceController {
     @GetMapping(value = "/sorted/{pid}/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
     public String sortList(@PathVariable(value = "pid") int pid,
                            @PathVariable(value = "id", required = false) Menu menu) {
-        Map<Integer, String> map = resourceService.getMapByPid(pid);
+        Map<Integer, String> map = menuQuery.getMapByPid(pid);
         // 排除当前 menu
         if (menu != null) {
             map.remove(menu.getPos());

+ 9 - 8
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/controller/ResourcePageController.java

@@ -1,10 +1,11 @@
 package cn.reghao.autodop.dmaster.auth.controller;
 
+import cn.reghao.autodop.dmaster.auth.db.query.MenuQuery;
 import cn.reghao.autodop.dmaster.auth.db.query.RoleQuery;
+import cn.reghao.autodop.dmaster.auth.entity.dto.MenuDTO;
 import cn.reghao.autodop.dmaster.auth.entity.po.Role;
 import cn.reghao.autodop.dmaster.auth.entity.po.Menu;
 import cn.reghao.autodop.dmaster.auth.entity.vo.MenuVO;
-import cn.reghao.autodop.dmaster.auth.service.ResourceService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.stereotype.Controller;
@@ -21,12 +22,12 @@ import java.util.*;
 @RequestMapping("/auth/menu")
 @Controller
 public class ResourcePageController {
-    private RoleQuery roleQuery;
-    private ResourceService resourceService;
+    private final RoleQuery roleQuery;
+    private final MenuQuery menuQuery;
 
-    public ResourcePageController(RoleQuery roleQuery, ResourceService resourceService) {
+    public ResourcePageController(RoleQuery roleQuery, MenuQuery menuQuery) {
         this.roleQuery = roleQuery;
-        this.resourceService = resourceService;
+        this.menuQuery = menuQuery;
     }
 
     @ApiOperation(value = "资源列表页面")
@@ -46,7 +47,7 @@ public class ResourcePageController {
         // 父级菜单
         Menu pMenu = null;
         if (pid != null) {
-            pMenu = resourceService.getResourceById(pid);
+            pMenu = menuQuery.getResourceById(pid);
         }
 
         Set<Role> allRoles = roleQuery.getAllRoles();
@@ -66,7 +67,7 @@ public class ResourcePageController {
         if (pid == 0) {
             pMenu = new Menu(pid, "根菜单");
         } else {
-            pMenu = resourceService.getResourceById(pid);
+            pMenu = menuQuery.getResourceById(pid);
         }
 
         Set<Role> allRoles = roleQuery.getAllRoles();
@@ -74,7 +75,7 @@ public class ResourcePageController {
 
         model.addAttribute("allRoles", allRoles);
         model.addAttribute("menuRoles", menuRoles);
-        model.addAttribute("menu", new MenuVO(menu));
+        model.addAttribute("menu", new MenuDTO(menu));
         model.addAttribute("pMenu", pMenu);
         return "/auth/menu/edit";
     }

+ 31 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/db/query/MenuQuery.java

@@ -4,7 +4,8 @@ import cn.reghao.autodop.dmaster.auth.entity.po.Menu;
 import cn.reghao.autodop.dmaster.auth.repository.MenuRepository;
 import org.springframework.stereotype.Service;
 
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -12,7 +13,7 @@ import java.util.List;
  */
 @Service
 public class MenuQuery {
-    private MenuRepository menuRepository;
+    private final MenuRepository menuRepository;
 
     public MenuQuery(MenuRepository menuRepository) {
         this.menuRepository = menuRepository;
@@ -21,4 +22,32 @@ public class MenuQuery {
     public List<Menu> getAllMenus() {
         return menuRepository.findAll();
     }
+
+    public List<Menu> getResourceByStatus(Boolean isEnabled) {
+        List<Menu> menuList = menuRepository.findByIsEnabled(isEnabled);
+        Map<Integer, List<Menu>> map =  menuList.stream().collect(Collectors.groupingBy(Menu::getPid));
+        List<Menu> list = new ArrayList<>();
+        map.forEach((pid, menus) -> {
+            list.addAll(menus.stream()
+                    .sorted(Comparator.comparing(Menu::getPos))
+                    .peek(menu -> menu.setChildren(null))
+                    .collect(Collectors.toList()));
+        });
+
+        return list;
+    }
+
+    public Map<Integer, String> getMapByPid(int pid) {
+        List<Menu> menus = menuRepository.findByPid(pid);
+        menus.sort(Comparator.comparingInt(Menu::getPos));
+        Map<Integer, String> map = new HashMap<>();
+        menus.forEach(menu -> {
+            map.put(menu.getPos(), menu.getName());
+        });
+        return map;
+    }
+
+    public Menu getResourceById(int id) {
+        return menuRepository.findById(id).orElse(null);
+    }
 }

+ 3 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/MenuType.java

@@ -1,9 +1,11 @@
 package cn.reghao.autodop.dmaster.auth.entity;
 
 /**
+ * 菜单类型
+ *
  * @author reghao
  * @date 2021-04-05 02:22:44
  */
 public enum MenuType {
-    DIR, PAGE
+    dir, page
 }

+ 2 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/UserGender.java

@@ -4,6 +4,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 /**
+ * 用户性别
+ *
  * @author reghao
  * @date 2021-07-14 10:23:46
  */

+ 46 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/dto/MenuDTO.java

@@ -0,0 +1,46 @@
+package cn.reghao.autodop.dmaster.auth.entity.dto;
+
+import cn.reghao.autodop.dmaster.auth.entity.po.Menu;
+import cn.reghao.autodop.dmaster.auth.entity.po.Role;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * @author reghao
+ * @date 2021-07-15 14:06:13
+ */
+@NoArgsConstructor
+@Data
+public class MenuDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @NotNull(message = "菜单 ID 不能为 NULL")
+    private Integer menuId;
+    // 父级菜单 ID
+    @NotNull(message = "父级菜单不能为 NULL")
+    private Integer pid;
+    // 在同一个 pid 组内的位置,作为排序使用
+    private Integer pos;
+    @NotBlank(message = "菜单名不能为空白字符串")
+    private String name;
+    @NotBlank(message = "URL 地址不能为空白字符串,目录类型使用可使用 # 字符")
+    private String url;
+    private String icon;
+    @NotNull(message = "角色不能为 NULL")
+    @JsonIgnore
+    private Set<Role> roles;
+
+    public MenuDTO(Menu menu) {
+        this.menuId = menu.getId();
+        this.pid = menu.getPid();
+        this.pos = menu.getPos();
+        this.name = menu.getName();
+        this.url = menu.getUrl();
+        this.icon = menu.getIcon();
+    }
+}

+ 2 - 16
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/vo/MenuVO.java

@@ -2,39 +2,25 @@ package cn.reghao.autodop.dmaster.auth.entity.vo;
 
 import cn.reghao.autodop.dmaster.auth.entity.po.Menu;
 import lombok.Data;
-import lombok.NoArgsConstructor;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
 import java.io.Serializable;
 
 /**
  * @author reghao
  * @date 2021-07-15 14:06:13
  */
-@NoArgsConstructor
 @Data
 public class MenuVO implements Serializable {
     private static final long serialVersionUID = 1L;
-    @NotNull(message = "菜单 ID 不能为 NULL")
     private Integer menuId;
-    // 父级菜单 ID
-    @NotNull(message = "父级菜单不能为 NULL")
-    private Integer pid;
-    // 在同一个 pid 组内的位置,作为排序使用
-    private Integer pos;
-    @NotBlank(message = "菜单名不能为空白字符串")
     private String name;
-    @NotBlank(message = "URL 地址不能为空白字符串,目录类型使用可使用 # 字符")
     private String url;
-    private String icon;
+    private String type;
 
     public MenuVO(Menu menu) {
         this.menuId = menu.getId();
-        this.pid = menu.getPid();
-        this.pos = menu.getPos();
         this.name = menu.getName();
         this.url = menu.getUrl();
-        this.icon = menu.getIcon();
+        this.type = menu.getType();
     }
 }

+ 16 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/MenuService.java

@@ -0,0 +1,16 @@
+package cn.reghao.autodop.dmaster.auth.service;
+
+import cn.reghao.autodop.common.result.Result;
+import cn.reghao.autodop.dmaster.auth.entity.dto.MenuDTO;
+import cn.reghao.autodop.dmaster.auth.entity.po.Menu;
+
+/**
+ * @author reghao
+ * @date 2021-07-21 15:17:14
+ */
+public interface MenuService {
+    Result addMenu(Menu menu);
+    Result updateMenu(MenuDTO menuDTO);
+    Result deleteMenu(Integer menuId);
+    Result setStatus(Integer menuId, boolean enable);
+}

+ 88 - 70
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/ResourceService.java → dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/MenuServiceImpl.java

@@ -1,9 +1,12 @@
 package cn.reghao.autodop.dmaster.auth.service;
 
+import cn.reghao.autodop.common.result.Result;
+import cn.reghao.autodop.common.result.ResultStatus;
+import cn.reghao.autodop.dmaster.auth.db.query.MenuQuery;
 import cn.reghao.autodop.dmaster.auth.entity.MenuType;
+import cn.reghao.autodop.dmaster.auth.entity.dto.MenuDTO;
 import cn.reghao.autodop.dmaster.auth.entity.po.Menu;
 import cn.reghao.autodop.dmaster.auth.entity.po.Role;
-import cn.reghao.autodop.dmaster.auth.entity.vo.MenuVO;
 import cn.reghao.autodop.dmaster.auth.repository.MenuRepository;
 import cn.reghao.autodop.dmaster.auth.repository.RoleRepository;
 import lombok.extern.slf4j.Slf4j;
@@ -19,64 +22,68 @@ import java.util.stream.Collectors;
  */
 @Slf4j
 @Service
-public class ResourceService {
+public class MenuServiceImpl implements MenuService {
     private final MenuRepository menuRepository;
-    private RoleRepository roleRepository;
+    private final RoleRepository roleRepository;
+    private final MenuQuery menuQuery;
 
-    public ResourceService(MenuRepository menuRepository, RoleRepository roleRepository) {
+    public MenuServiceImpl(MenuRepository menuRepository, RoleRepository roleRepository, MenuQuery menuQuery) {
         this.menuRepository = menuRepository;
         this.roleRepository = roleRepository;
+        this.menuQuery = menuQuery;
     }
 
-    public synchronized void addResource(Menu menu) {
-        // menu 最多只能有两个 parent,即最多只能有三级菜单
-        if (!checkMenu(menu.getPid())) {
-            return;
+    @Override
+    public synchronized Result addMenu(Menu menu) {
+        Result result = moreThanTwoParents(menu.getPid());
+        if (result.getCode() != ResultStatus.SUCCESS.getCode()) {
+            return result;
         }
+
         // 调整 menu 组内元素的位置
-        adjustPosition(menu);
+        insertNewMenu(menu);
         menu.setIsEnabled(true);
         Menu menuEntity = menuRepository.save(menu);
 
         Set<Role> roles = menu.getRoles();
         roles.forEach(role -> role.getMenus().add(menuEntity));
         roleRepository.saveAll(roles);
+        return Result.result(ResultStatus.SUCCESS);
     }
 
     /**
-     * 检查菜单的层级
+     * 检查菜单的层级, Menu 最多只能有两个 parent, 即最多只能有三级菜单
      *
      * @param
      * @return
      * @date 2021-07-15 上午11:15
      */
-    private boolean checkMenu(int pid) {
+    private Result moreThanTwoParents(int pid) {
         if (pid != 0) {
-            Menu menu1 = getResourceById(pid);
+            Menu menu1 = menuQuery.getResourceById(pid);
             int pid1 = menu1.getPid();
             if (pid1 != 0) {
-                Menu menu2 = getResourceById(pid1);
+                Menu menu2 = menuQuery.getResourceById(pid1);
                 int pid2 = menu2.getPid();
                 if (pid2 != 0) {
-                    log.error("menu 最多只能有两个 parent,即最多只能有三级菜单...");
-                    return false;
+                    return Result.result(ResultStatus.FAIL, "Menu 最多只能有两个 parent,即最多只能有三级菜单...");
                 }
             }
         }
 
-        return true;
+        return Result.result(ResultStatus.SUCCESS);
     }
 
     /**
-     * 调整同一 pid 组内 menu 的位置
+     * 向 menu 组插入元素时调整组内 menu 的位置
      *
      * @date 2021-05-18 上午9:54
      */
-    private void adjustPosition(Menu menu) {
+    private void insertNewMenu(Menu menu) {
         int pid = menu.getPid();
         if (pid != 0) {
             Menu pMenu = menuRepository.getOne(pid);
-            if (pMenu.getType().equals(MenuType.PAGE.name())) {
+            if (pMenu.getType().equals(MenuType.page.name())) {
                 log.error("父级菜单的类型不能是 PAGE");
                 return;
             }
@@ -108,7 +115,7 @@ public class ResourceService {
     }
 
     /**
-     * 向后移动元素
+     * 向后移动元素(向 menu 组新增元素时调用)
      *
      * @return
      * @date 2021-07-15 下午5:07
@@ -123,7 +130,7 @@ public class ResourceService {
     }
 
     /**
-     * 向前移动元素
+     * 向前移动元素(从 menu 组删除元素时调用)
      *
      * @param
      * @return
@@ -138,45 +145,77 @@ public class ResourceService {
         menuRepository.saveAll(menus);
     }
 
-    public synchronized void updateResource(MenuVO vo, Set<Role> roles) {
-        int menuId = vo.getMenuId();
+    @Override
+    public synchronized Result updateMenu(MenuDTO menuDTO) {
+        int menuId = menuDTO.getMenuId();
         Menu menuEntity = menuRepository.findById(menuId).orElse(null);
         if (menuEntity == null) {
-            log.error("menu 不存在");
-            return;
-        }
-
-        int pid = vo.getPid();
-        if (!checkMenu(pid)) {
-            return;
-        }
-
-        if (pid != menuEntity.getPid()) {
-            // TODO menu 更换到了新的 menu 组
-            return;
+            return Result.result(ResultStatus.FAIL, String.format("ID 为 %s 的 Menu 不存在", menuId));
         }
 
         int oldPos = menuEntity.getPos();
         // menu 的新位置
-        int pos = vo.getPos()+1;
-        if (oldPos != pos) {
-            // TODO menu 在组内的位置发生变化
-            List<Menu> menus = menuRepository.findByPid(pid);
-            menus.sort(Comparator.comparingInt(Menu::getPos));
-            System.out.println();
+        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);
         }
 
-        menuEntity.setName(vo.getName());
-        menuEntity.setUrl(vo.getUrl());
-        menuEntity.setIcon(vo.getIcon());
+        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(roles);
+        return Result.result(ResultStatus.SUCCESS);
     }
 
-    public synchronized void deleteResource(Menu menu) {
+    /**
+     * 对组内的菜单进行重排序,只需调整 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);
+            }
+        }
+        menuRepository.saveAll(map.values());
+    }
+
+    @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));
+        }
+
         // 删除 Role 关联的 Menu
         for (Role role : menu.getRoles()) {
             role.getMenus().remove(menu);
@@ -190,33 +229,12 @@ public class ResourceService {
         int pos = menu.getPos();
         moveForward(menus, pos);
         menuRepository.delete(menu);
+        return Result.result(ResultStatus.SUCCESS);
     }
 
-    public List<Menu> getResourceByStatus(Boolean isEnabled) {
-        List<Menu> menuList = menuRepository.findByIsEnabled(isEnabled);
-        Map<Integer, List<Menu>> map =  menuList.stream().collect(Collectors.groupingBy(Menu::getPid));
-        List<Menu> list = new ArrayList<>();
-        map.forEach((pid, menus) -> {
-            list.addAll(menus.stream()
-                    .sorted(Comparator.comparing(Menu::getPos))
-                    .peek(menu -> menu.setChildren(null))
-                    .collect(Collectors.toList()));
-        });
-
-        return list;
-    }
-
-    public Map<Integer, String> getMapByPid(int pid) {
-        List<Menu> menus = menuRepository.findByPid(pid);
-        menus.sort(Comparator.comparingInt(Menu::getPos));
-        Map<Integer, String> map = new HashMap<>();
-        menus.forEach(menu -> {
-            map.put(menu.getPos(), menu.getName());
-        });
-        return map;
-    }
+    @Override
+    public Result setStatus(Integer menuId, boolean enable) {
 
-    public Menu getResourceById(int id) {
-        return menuRepository.findById(id).orElse(null);
+        return Result.result(ResultStatus.SUCCESS);
     }
 }

+ 1 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/RoleServiceImpl.java

@@ -20,7 +20,7 @@ import java.util.Set;
 public class RoleServiceImpl implements RoleService {
     private final String rolePrefix = "ROLE_";
     private final RoleRepository roleRepository;
-    private RoleQuery roleQuery;
+    private final RoleQuery roleQuery;
 
     public RoleServiceImpl(RoleRepository roleRepository, RoleQuery roleQuery) {
         this.roleRepository = roleRepository;
@@ -34,7 +34,6 @@ public class RoleServiceImpl implements RoleService {
         roleRepository.save(role);
     }
 
-    // TODO 待实现
     @Override
     public void delete(Integer roleId) {
         Role role = roleQuery.getRoleById(roleId);

+ 5 - 5
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/controller/MachinePageController.java

@@ -1,7 +1,7 @@
 package cn.reghao.autodop.dmaster.machine.controller;
 
 import cn.reghao.autodop.common.utils.DateTimeConverter;
-import cn.reghao.autodop.dmaster.app.constant.EnvType;
+import cn.reghao.autodop.dmaster.app.constant.EnvList;
 import cn.reghao.autodop.dmaster.app.vo.KeyValue;
 import cn.reghao.autodop.dmaster.machine.db.crud.MachineInfoCrudService;
 import cn.reghao.autodop.dmaster.machine.db.query.MachineQuery;
@@ -63,7 +63,7 @@ public class MachinePageController {
                            @RequestParam(value = "machineIpv4", required = false) String machineIpv4,
                            Model model) {
         if (env == null) {
-            env = EnvType.test.name();
+            env = EnvList.test.name();
         }
 
         if (machineIpv4 != null) {
@@ -144,8 +144,8 @@ public class MachinePageController {
     @GetMapping("/host/edit/{machineId}")
     public String hostEditPage(@PathVariable("machineId") String machineId, Model model) {
         List<KeyValue> envs = new ArrayList<>();
-        for (EnvType envType : EnvType.values()) {
-            envs.add(new KeyValue(envType.name(), envType.name()));
+        for (EnvList envList : EnvList.values()) {
+            envs.add(new KeyValue(envList.name(), envList.name()));
         }
 
         MachineHost machineHost = machineQuery.query(machineId);
@@ -169,7 +169,7 @@ public class MachinePageController {
                              @RequestParam(value = "machineIpv4", required = false) String machineIpv4,
                              Model model) {
         if (env == null) {
-            env = EnvType.test.name();
+            env = EnvList.test.name();
         }
 
         if (machineIpv4 != null) {

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/machine/entity/po/MachineHost.java

@@ -1,6 +1,6 @@
 package cn.reghao.autodop.dmaster.machine.entity.po;
 
-import cn.reghao.autodop.dmaster.app.constant.EnvType;
+import cn.reghao.autodop.dmaster.app.constant.EnvList;
 import cn.reghao.autodop.dmaster.common.orm.BaseEntity;
 import cn.reghao.autodop.dmaster.machine.entity.po.info.MachineInfo;
 import cn.reghao.autodop.dmaster.notification.entity.NotifyGroup;
@@ -38,7 +38,7 @@ public class MachineHost extends BaseEntity<Integer> {
 
     public MachineHost(MachineInfo machineInfo) {
         this.machineInfo = machineInfo;
-        this.env = EnvType.test.name();
+        this.env = EnvList.test.name();
         this.status = MachineStatus.UP.name();
         this.lastCheck = LocalDateTime.now();
     }

+ 5 - 5
dmaster/src/main/java/cn/reghao/autodop/dmaster/sys/controller/TestController.java

@@ -76,7 +76,7 @@ public class TestController {
         homeMenu.setPos(1);
         homeMenu.setName("主页");
         homeMenu.setUrl("/home");
-        homeMenu.setType(MenuType.PAGE.name());
+        homeMenu.setType(MenuType.page.name());
         homeMenu.setIcon("layui-icon layui-icon-home");
         menus.add(homeMenu);
 
@@ -85,7 +85,7 @@ public class TestController {
         sysMenu.setPos(2);
         sysMenu.setName("系统管理");
         sysMenu.setUrl("#");
-        sysMenu.setType(MenuType.DIR.name());
+        sysMenu.setType(MenuType.dir.name());
         sysMenu.setIcon("fa fa-cog");
         menus.add(sysMenu);
         menuRepository.saveAll(menus);
@@ -96,7 +96,7 @@ public class TestController {
         userMenu.setPos(1);
         userMenu.setName("用户管理");
         userMenu.setUrl("/system/user");
-        userMenu.setType(MenuType.PAGE.name());
+        userMenu.setType(MenuType.page.name());
         userMenu.setIcon("fa fa-cog");
         menus.add(userMenu);
 
@@ -105,7 +105,7 @@ public class TestController {
         roleMenu.setPos(2);
         roleMenu.setName("角色管理");
         roleMenu.setUrl("/system/role");
-        roleMenu.setType(MenuType.PAGE.name());
+        roleMenu.setType(MenuType.page.name());
         roleMenu.setIcon("fa fa-cog");
         menus.add(roleMenu);
 
@@ -114,7 +114,7 @@ public class TestController {
         resourceMenu.setPos(3);
         resourceMenu.setName("资源管理");
         resourceMenu.setUrl("/system/user/menu");
-        resourceMenu.setType(MenuType.PAGE.name());
+        resourceMenu.setType(MenuType.page.name());
         resourceMenu.setIcon("fa fa-cog");
         menus.add(resourceMenu);
         menuRepository.saveAll(menus);

+ 8 - 7
dmaster/src/main/java/cn/reghao/autodop/dmaster/view/thymeleaf/attribute/SelectDictAttrProcessor.java

@@ -1,5 +1,7 @@
 package cn.reghao.autodop.dmaster.view.thymeleaf.attribute;
 
+import cn.reghao.autodop.dmaster.app.constant.EnvList;
+import cn.reghao.autodop.dmaster.auth.entity.MenuType;
 import org.thymeleaf.IEngineConfiguration;
 import org.thymeleaf.context.ITemplateContext;
 import org.thymeleaf.engine.AttributeName;
@@ -25,15 +27,14 @@ public class SelectDictAttrProcessor extends AbstractAttributeTagProcessor {
         localCache.get("MENU_STATUS").put("DISABLE", false);
 
         localCache.put("MENU_TYPE", new HashMap<>());
-        localCache.get("MENU_TYPE").put("DIR", "DIR");
-        localCache.get("MENU_TYPE").put("PAGE", "PAGE");
+        for (MenuType menuType : MenuType.values()) {
+            localCache.get("MENU_TYPE").put(menuType.name(), menuType.name());
+        }
 
-        // TODO 指定默认环境
         localCache.put("ENVIRONMENT", new HashMap<>());
-        localCache.get("ENVIRONMENT").put("dev", "dev");
-        localCache.get("ENVIRONMENT").put("test", "test");
-        localCache.get("ENVIRONMENT").put("uat", "uat");
-        localCache.get("ENVIRONMENT").put("prod", "prod");
+        for (EnvList env : EnvList.values()) {
+            localCache.get("ENVIRONMENT").put(env.name(), env.name());
+        }
     }
     
     public static final int PRECEDENCE = 1400;

+ 1 - 1
dmaster/src/main/resources/templates/auth/menu/index.html

@@ -66,7 +66,7 @@
                                     </th>
                                     <th>名称</th>
                                     <th>URL 地址</th>
-                                    <th>资源类型</th>
+                                    <th>菜单类型</th>
                                     <th>可访问的角色</th>
                                     <th>操作</th>
                                 </tr>

+ 5 - 18
pom.xml

@@ -38,6 +38,11 @@
     </repositories>
 
     <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-devtools</artifactId>
@@ -57,29 +62,11 @@
             <optional>true</optional>
         </dependency>
 
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-aop</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>javax.validation</groupId>
-            <artifactId>validation-api</artifactId>
-            <version>2.0.1.Final</version>
-        </dependency>
-
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <version>1.18.0</version>
             <scope>provided</scope>
         </dependency>
-
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter</artifactId>
-            <version>RELEASE</version>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 </project>