Browse Source

构建配置部分的前端页面基本完成

reghao 5 years ago
parent
commit
6f719d9379
30 changed files with 782 additions and 648 deletions
  1. 2 2
      common/src/main/java/cn/reghao/autodop/common/dagent/app/api/data/deploy/PackType.java
  2. 7 7
      dagent/src/main/java/cn/reghao/autodop/dagent/app/App.java
  3. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/ConfigController.java
  4. 1 7
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/AppConfigPageController.java
  5. 180 14
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/BuildConfigPageController.java
  6. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/db/config/PackerConfigCrudService.java
  7. 0 15
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/build/BuildConfig.java
  8. 2 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/build/BuildDir.java
  9. 1 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/build/CompilerConfig.java
  10. 1 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/build/PackerConfig.java
  11. 2 2
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/AppIntegrate.java
  12. 0 24
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/vo/CurrentRunningCommit.java
  13. 15 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/vo/KeyValue.java
  14. 0 17
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/vo/SuccessfullyBuildVO.java
  15. 4 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/lifecycle/AfterAppStart.java
  16. 0 267
      dmaster/src/main/resources/templates/app/config/app/add.bak.html
  17. 1 1
      dmaster/src/main/resources/templates/app/config/app/add.html
  18. 50 0
      dmaster/src/main/resources/templates/app/config/builddir/add.html
  19. 63 0
      dmaster/src/main/resources/templates/app/config/builddir/index.html
  20. 52 0
      dmaster/src/main/resources/templates/app/config/compiler/add.html
  21. 31 0
      dmaster/src/main/resources/templates/app/config/compiler/detail.html
  22. 65 0
      dmaster/src/main/resources/templates/app/config/compiler/index.html
  23. 46 0
      dmaster/src/main/resources/templates/app/config/packer/add.html
  24. 25 0
      dmaster/src/main/resources/templates/app/config/packer/detail.html
  25. 65 0
      dmaster/src/main/resources/templates/app/config/packer/index.html
  26. 0 87
      dmaster/src/main/resources/templates/app/config/proj/index.html
  27. 66 0
      dmaster/src/main/resources/templates/app/config/repoauth/add.html
  28. 35 0
      dmaster/src/main/resources/templates/app/config/repoauth/detail.html
  29. 63 0
      dmaster/src/main/resources/templates/app/config/repoauth/index.html
  30. 1 196
      dmaster/src/main/resources/templates/home/index.html

+ 2 - 2
common/src/main/java/cn/reghao/autodop/common/dagent/app/api/data/deploy/PackerType.java → common/src/main/java/cn/reghao/autodop/common/dagent/app/api/data/deploy/PackType.java

@@ -1,11 +1,11 @@
 package cn.reghao.autodop.common.dagent.app.api.data.deploy;
 
 /**
- * 打包类型
+ * 打包方式类型
  *
  * @author reghao
  * @date 2019-11-15 21:59:35
  */
-public enum PackerType {
+public enum PackType {
     docker, zip;
 }

+ 7 - 7
dagent/src/main/java/cn/reghao/autodop/dagent/app/App.java

@@ -4,7 +4,7 @@ import cn.reghao.autodop.common.dagent.app.api.data.AppIdArgs;
 import cn.reghao.autodop.common.dagent.app.api.data.AppStatus;
 import cn.reghao.autodop.common.dagent.app.api.data.DeployResult;
 import cn.reghao.autodop.common.dagent.app.api.data.deploy.AppDeployArgs;
-import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackerType;
+import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackType;
 import cn.reghao.autodop.common.dagent.app.api.data.log.AppLogArgs;
 import cn.reghao.autodop.common.dagent.app.api.data.log.LogConfig;
 import cn.reghao.autodop.common.dagent.app.api.data.log.LogFile;
@@ -48,7 +48,7 @@ public class App {
 
         AppStatus appStatus;
         DeployResult deployResult = new DeployResult(buildLogId, machineId, machineIpv4);
-        switch (PackerType.valueOf(packerType)) {
+        switch (PackType.valueOf(packerType)) {
             case docker:
                 try {
                     appStatus = dockerAppServiceImpl.deploy(appDeployArgs);
@@ -79,7 +79,7 @@ public class App {
             String packerType = appLogArgs.getPackerType();
             long count = appLogArgs.getLogConfigs().stream().filter(LogConfig::getIsDir).count();
 
-            switch (PackerType.valueOf(packerType)) {
+            switch (PackType.valueOf(packerType)) {
                 case docker:
                     if (count > 0) {
                         List<LogFile> logFiles = dockerAppServiceImpl.logFiles(appLogArgs);
@@ -110,7 +110,7 @@ public class App {
         String packerType = appIdArgs.getPackerType();
 
         AppStatus appStatus;
-        switch (PackerType.valueOf(packerType)) {
+        switch (PackType.valueOf(packerType)) {
             case docker:
                 try {
                     appStatus = dockerAppServiceImpl.status(appId);
@@ -133,7 +133,7 @@ public class App {
         String packerType = appIdArgs.getPackerType();
 
         AppStatus appStatus;
-        switch (PackerType.valueOf(packerType)) {
+        switch (PackType.valueOf(packerType)) {
             case docker:
                 try {
                     appStatus = dockerAppServiceImpl.restart(appId);
@@ -156,7 +156,7 @@ public class App {
         String packerType = appIdArgs.getPackerType();
 
         AppStatus appStatus;
-        switch (PackerType.valueOf(packerType)) {
+        switch (PackType.valueOf(packerType)) {
             case docker:
                 try {
                     appStatus = dockerAppServiceImpl.stop(appId);
@@ -179,7 +179,7 @@ public class App {
         String packerType = appIdArgs.getPackerType();
 
         AppStatus appStatus;
-        switch (PackerType.valueOf(packerType)) {
+        switch (PackType.valueOf(packerType)) {
             case docker:
                 try {
                     appStatus = dockerAppServiceImpl.start(appId);

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

@@ -1,6 +1,6 @@
 package cn.reghao.autodop.dmaster.app.controller;
 
-import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackerType;
+import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackType;
 import cn.reghao.autodop.dmaster.utils.WebBody;
 import cn.reghao.autodop.dmaster.app.constant.*;
 import cn.reghao.autodop.dmaster.app.constant.build.CompileType;
@@ -63,7 +63,7 @@ public class ConfigController {
                 }
                 break;
             case packer:
-                for (PackerType config : PackerType.values()) {
+                for (PackType config : PackType.values()) {
                     map.put(config.name(), config.name());
                 }
                 break;

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

@@ -9,6 +9,7 @@ import cn.reghao.autodop.dmaster.app.repository.config.AppOrchestrationRepositor
 import cn.reghao.autodop.dmaster.app.repository.config.build.CompilerConfigRepository;
 import cn.reghao.autodop.dmaster.app.repository.config.build.PackerConfigRepository;
 import cn.reghao.autodop.dmaster.app.repository.config.build.RepoAuthConfigRepository;
+import cn.reghao.autodop.dmaster.app.vo.KeyValue;
 import cn.reghao.autodop.dmaster.machine.entity.NetworkInfo;
 import cn.reghao.autodop.dmaster.machine.repository.MachineInfoRepository;
 import cn.reghao.autodop.dmaster.utils.db.PageList;
@@ -180,11 +181,4 @@ public class AppConfigPageController {
         model.addAttribute("list", pageList.getList());
         return "/app/config/proj/index";
     }
-
-    @AllArgsConstructor
-    @Data
-    class KeyValue {
-        private String key;
-        private String value;
-    }
 }

+ 180 - 14
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/view/BuildConfigPageController.java

@@ -1,16 +1,34 @@
 package cn.reghao.autodop.dmaster.app.controller.view;
 
-import cn.reghao.autodop.dmaster.app.constant.EnvType;
+import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackType;
+import cn.reghao.autodop.dmaster.app.constant.build.CompileType;
+import cn.reghao.autodop.dmaster.app.constant.build.RepoAuthType;
+import cn.reghao.autodop.dmaster.app.constant.build.RepoType;
+import cn.reghao.autodop.dmaster.app.entity.config.build.BuildDir;
+import cn.reghao.autodop.dmaster.app.entity.config.build.CompilerConfig;
+import cn.reghao.autodop.dmaster.app.entity.config.build.PackerConfig;
+import cn.reghao.autodop.dmaster.app.entity.config.build.RepoAuthConfig;
+import cn.reghao.autodop.dmaster.app.repository.config.build.BuildDirRepository;
+import cn.reghao.autodop.dmaster.app.repository.config.build.CompilerConfigRepository;
+import cn.reghao.autodop.dmaster.app.repository.config.build.PackerConfigRepository;
+import cn.reghao.autodop.dmaster.app.repository.config.build.RepoAuthConfigRepository;
+import cn.reghao.autodop.dmaster.app.vo.KeyValue;
+import cn.reghao.autodop.dmaster.utils.db.PageList;
+import cn.reghao.autodop.dmaster.utils.db.PageSort;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @author reghao
  * @date 2019-08-30 18:49:15
@@ -20,17 +38,165 @@ import org.springframework.web.bind.annotation.RequestMapping;
 @Controller
 @RequestMapping("/app/config/build")
 public class BuildConfigPageController {
-    public BuildConfigPageController() {
-    }
-
-    @ApiOperation(value = "构建页面")
-    @GetMapping("/repo")
-    public String buildPage(Model model) {
-        String env = EnvType.test.name();
-        int page = 1;
-        int size = 10;
-        PageRequest pageRequest =
-                PageRequest.of(page-1, size, Sort.by(Sort.Direction.DESC, "updateTime"));
-        return "/app/build";
+    private BuildDirRepository buildDirRepository;
+    private RepoAuthConfigRepository repoAuthRepository;
+    private CompilerConfigRepository compilerRepository;
+    private PackerConfigRepository packerRepository;
+
+    public BuildConfigPageController(BuildDirRepository buildDirRepository,
+                                     RepoAuthConfigRepository repoAuthRepository,
+                                     CompilerConfigRepository compilerRepository,
+                                     PackerConfigRepository packerRepository) {
+        this.buildDirRepository = buildDirRepository;
+        this.repoAuthRepository = repoAuthRepository;
+        this.compilerRepository = compilerRepository;
+        this.packerRepository = packerRepository;
+    }
+
+    @ApiOperation(value = "构建目录页面")
+    @GetMapping("/dir")
+    public String buildDirPage(Model model) {
+        PageRequest pageRequest = PageSort.pageRequest();
+        Page<BuildDir> page = buildDirRepository.findAll(pageRequest);
+        PageList<BuildDir> pageList = PageList.pageList(page);
+
+        model.addAttribute("page", page);
+        model.addAttribute("list", pageList.getList());
+        return "/app/config/builddir/index";
+    }
+
+    @GetMapping("/dir/add")
+    public String addAppConfigPage(Model model) {
+        return "/app/config/builddir/add";
+    }
+
+    @GetMapping("/dir/edit/{id}")
+    public String editAppConfigPage(@PathVariable("id") BuildDir buildDir, Model model) {
+        model.addAttribute("buildDir", buildDir);
+        return "/app/config/builddir/add";
+    }
+
+    @ApiOperation(value = "仓库认证页面")
+    @GetMapping("/repoauth")
+    public String repoAuthPage(Model model) {
+        PageRequest pageRequest = PageSort.pageRequest();
+        Page<RepoAuthConfig> page = repoAuthRepository.findAll(pageRequest);
+        PageList<RepoAuthConfig> pageList = PageList.pageList(page);
+
+        model.addAttribute("page", page);
+        model.addAttribute("list", pageList.getList());
+        return "/app/config/repoauth/index";
+    }
+
+    @GetMapping("/repoauth/add")
+    public String addRepoAuthPage(Model model) {
+        setRepoAuthModel(model);
+        return "/app/config/repoauth/add";
+    }
+
+    @GetMapping("/repoauth/edit/{id}")
+    public String editRepoAuthPage(@PathVariable("id") RepoAuthConfig repoAuth, Model model) {
+        setRepoAuthModel(model);
+        model.addAttribute("repoAuth", repoAuth);
+        return "/app/config/repoauth/add";
+    }
+
+    private void setRepoAuthModel(Model model) {
+        List<KeyValue> repos = new ArrayList<>();
+        for (RepoType repoType : RepoType.values()) {
+            repos.add(new KeyValue(repoType.name(), repoType.name()));
+        }
+
+        List<KeyValue> auths = new ArrayList<>();
+        for (RepoAuthType authType : RepoAuthType.values()) {
+            auths.add(new KeyValue(authType.name(), authType.name()));
+        }
+
+        model.addAttribute("repos", repos);
+        model.addAttribute("auths", auths);
+    }
+
+    @GetMapping("/repoauth/detail/{id}")
+    public String repoAuthDetailPage(@PathVariable("id") RepoAuthConfig repoAuth, Model model) {
+        model.addAttribute("repoAuth", repoAuth);
+        return "/app/config/repoauth/detail";
+    }
+
+    @ApiOperation(value = "编译配置页面")
+    @GetMapping("/compiler")
+    public String compilerConfigPage(Model model) {
+        PageRequest pageRequest = PageSort.pageRequest();
+        Page<CompilerConfig> page = compilerRepository.findAll(pageRequest);
+        PageList<CompilerConfig> pageList = PageList.pageList(page);
+
+        model.addAttribute("page", page);
+        model.addAttribute("list", pageList.getList());
+        return "/app/config/compiler/index";
+    }
+
+    @GetMapping("/compiler/add")
+    public String addCompilerPage(Model model) {
+        setCompilerModel(model);
+        return "/app/config/compiler/add";
+    }
+
+    @GetMapping("/compiler/edit/{id}")
+    public String editCompilerPage(@PathVariable("id") CompilerConfig compilerConfig, Model model) {
+        setCompilerModel(model);
+        model.addAttribute("compiler", compilerConfig);
+        return "/app/config/compiler/add";
+    }
+
+    private void setCompilerModel(Model model) {
+        List<KeyValue> compileTypes = new ArrayList<>();
+        for (CompileType compileType : CompileType.values()) {
+            compileTypes.add(new KeyValue(compileType.name(), compileType.name()));
+        }
+        model.addAttribute("compileTypes", compileTypes);
+    }
+
+    @GetMapping("/compiler/detail/{id}")
+    public String compilerDetailPage(@PathVariable("id") CompilerConfig compilerConfig, Model model) {
+        model.addAttribute("compiler", compilerConfig);
+        return "/app/config/compiler/detail";
+    }
+
+    @ApiOperation(value = "打包配置页面")
+    @GetMapping("/packer")
+    public String packerPage(Model model) {
+        PageRequest pageRequest = PageSort.pageRequest();
+        Page<PackerConfig> page = packerRepository.findAll(pageRequest);
+        PageList<PackerConfig> pageList = PageList.pageList(page);
+
+        model.addAttribute("page", page);
+        model.addAttribute("list", pageList.getList());
+        return "/app/config/packer/index";
+    }
+
+    @GetMapping("/packer/add")
+    public String addPackerPage(Model model) {
+        setPackerModel(model);
+        return "/app/config/packer/add";
+    }
+
+    @GetMapping("/packer/edit/{id}")
+    public String editPackerPage(@PathVariable("id") PackerConfig packerConfig, Model model) {
+        setPackerModel(model);
+        model.addAttribute("packer", packerConfig);
+        return "/app/config/packer/add";
+    }
+
+    private void setPackerModel(Model model) {
+        List<KeyValue> packTypes = new ArrayList<>();
+        for (PackType packType : PackType.values()) {
+            packTypes.add(new KeyValue(packType.name(), packType.name()));
+        }
+        model.addAttribute("packTypes", packTypes);
+    }
+
+    @GetMapping("/packer/detail/{id}")
+    public String packerDetailPage(@PathVariable("id") PackerConfig packerConfig, Model model) {
+        model.addAttribute("packer", packerConfig);
+        return "/app/config/packer/detail";
     }
 }

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

@@ -3,7 +3,7 @@ package cn.reghao.autodop.dmaster.app.db.config;
 import cn.reghao.autodop.dmaster.common.db.CrudOps;
 import cn.reghao.autodop.dmaster.utils.db.PageList;
 import cn.reghao.autodop.dmaster.app.entity.config.build.PackerConfig;
-import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackerType;
+import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackType;
 import cn.reghao.autodop.dmaster.app.repository.config.build.PackerConfigRepository;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
@@ -26,7 +26,7 @@ public class PackerConfigCrudService implements CrudOps<PackerConfig> {
 
     @Override
     public void insert(PackerConfig packerConfig) {
-        if (PackerType.valueOf(packerConfig.getType()) == PackerType.docker) {
+        if (PackType.valueOf(packerConfig.getType()) == PackType.docker) {
             // TODO 检测本机上是否存在 docker
             // checkScript("docker -v");
         }

+ 0 - 15
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/build/BuildConfig.java

@@ -1,24 +1,9 @@
 package cn.reghao.autodop.dmaster.app.entity.config.build;
 
-import lombok.Data;
-
-import javax.persistence.*;
-
 /**
  * @author reghao
  * @date 2020-05-13 16:40:22
  */
 @Deprecated
-@Data
-@Embeddable
 public class BuildConfig {
-    @ManyToOne(cascade = CascadeType.PERSIST)
-    @JoinColumn(name = "repo_config_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
-    private RepoAuthConfig repoAuthConfig;
-    @ManyToOne(cascade = CascadeType.PERSIST)
-    @JoinColumn(name = "compiler_config_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
-    private CompilerConfig compilerConfig;
-    @ManyToOne(cascade = CascadeType.PERSIST)
-    @JoinColumn(name = "packer_config_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
-    private PackerConfig packerConfig;
 }

+ 2 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/build/BuildDir.java

@@ -20,9 +20,10 @@ public class BuildDir extends BaseEntity<Integer> {
     // 主机唯一标识
     @Column(nullable = false, unique = true)
     private String machineId;
+    private String machineIpv4;
     // 本地目录,包含 local-repo, compile-dir 和 pack-dir 三个子目录
     @Column(nullable = false)
-    private String localDir;
+    private String dirPath;
     // 总容量
     @Column(nullable = false)
     private String capacity;

+ 1 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/build/CompilerConfig.java

@@ -20,6 +20,7 @@ import javax.persistence.Entity;
 @Entity
 public class CompilerConfig extends BaseEntity<Integer> {
     private String machineId;
+    private String machineIpv4;
     @Column(nullable = false)
     private String type;
     @Column(nullable = false, unique = true)

+ 1 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/build/PackerConfig.java

@@ -21,6 +21,7 @@ import javax.persistence.Lob;
 @Entity
 public class PackerConfig extends BaseEntity<Integer> {
     private String machineId;
+    private String machineIpv4;
     @Column(nullable = false)
     private String type;
     @Column(nullable = false, unique = true)

+ 2 - 2
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/bd/AppIntegrate.java

@@ -1,6 +1,6 @@
 package cn.reghao.autodop.dmaster.app.service.bd;
 
-import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackerType;
+import cn.reghao.autodop.common.dagent.app.api.data.deploy.PackType;
 import cn.reghao.autodop.dmaster.app.constant.build.CompileType;
 import cn.reghao.autodop.dmaster.app.constant.build.RepoType;
 import cn.reghao.autodop.dmaster.app.entity.config.build.CompilerConfig;
@@ -119,7 +119,7 @@ public class AppIntegrate {
 
         // 初始化打包配置
         PackerConfig packerConfig = app.getPackerConfig();
-        switch (PackerType.valueOf(packerConfig.getType())) {
+        switch (PackType.valueOf(packerConfig.getType())) {
             case docker:
                 codePacker = new DockerPack(packerConfig, app.getDockerfile());
                 break;

+ 0 - 24
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/vo/CurrentRunningCommit.java

@@ -1,24 +0,0 @@
-package cn.reghao.autodop.dmaster.app.vo;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 应用当前运行的版本
- *
- * @author reghao
- * @date 2021-02-20 15:16:44
- */
-@AllArgsConstructor
-@NoArgsConstructor
-@Data
-public class CurrentRunningCommit {
-    private String machineId;
-    private String commitId;
-    private String deployTime;
-
-    public CurrentRunningCommit(String machineId) {
-        this.machineId = machineId;
-    }
-}

+ 15 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/vo/KeyValue.java

@@ -0,0 +1,15 @@
+package cn.reghao.autodop.dmaster.app.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @author reghao
+ * @date 2021-06-03 19:00:57
+ */
+@AllArgsConstructor
+@Data
+public class KeyValue {
+    private String key;
+    private String value;
+}

+ 0 - 17
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/vo/SuccessfullyBuildVO.java

@@ -1,17 +0,0 @@
-package cn.reghao.autodop.dmaster.app.vo;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-/**
- * @author reghao
- * @date 2020-06-02 14:32:45
- */
-@AllArgsConstructor
-@Data
-public class SuccessfullyBuildVO {
-    private String commitId;
-    private String commitMsg;
-    private String appPath;
-    private String buildTime;
-}

+ 4 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/lifecycle/AfterAppStart.java

@@ -66,7 +66,7 @@ public class AfterAppStart implements ApplicationRunner {
             if (diskInfo != null) {
                 buildDir = new BuildDir();
                 buildDir.setMachineId(machineId);
-                buildDir.setLocalDir(home + "/autodop");
+                buildDir.setDirPath(home + "/autodop");
                 buildDir.setCapacity(diskInfo.getSize());
                 buildDir.setUsed(diskInfo.getUsed());
                 buildDir.setAvailable(diskInfo.getAvail());
@@ -87,9 +87,9 @@ public class AfterAppStart implements ApplicationRunner {
 
     public void initialize(BuildDir buildDir) throws MqttException {
         // TODO 放入缓存
-        SysConfig.localRepo = buildDir.getLocalDir() + "/local-repo";
-        SysConfig.compileDir = buildDir.getLocalDir() + "/compile-dir";
-        SysConfig.packDir = buildDir.getLocalDir() + "/pack-dir";
+        SysConfig.localRepo = buildDir.getDirPath() + "/local-repo";
+        SysConfig.compileDir = buildDir.getDirPath() + "/compile-dir";
+        SysConfig.packDir = buildDir.getDirPath() + "/pack-dir";
         checkAndSetLocalDir();
         //userService.checkOrSetAdmin();
         sub();

+ 0 - 267
dmaster/src/main/resources/templates/app/config/app/add.bak.html

@@ -1,267 +0,0 @@
-<!DOCTYPE html>
-<html xmlns:th="http://www.thymeleaf.org">
-<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
-
-<body>
-<div class="layui-form timo-compile">
-    <form th:action="@{/app/config/app}">
-        <input type="hidden" name="id" th:if="${app}" th:value="${app?.id}"/>
-        <div class="timo-detail-title">基本信息</div>
-        <table class="layui-table timo-detail-table">
-            <tbody>
-            <tr>
-                <th>应用 ID</th>
-                <td>
-                    <div class="layui-form-item" th:if="!${app}">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="appId"  placeholder="请输入应用 ID" required th:value="${app?.appId}">
-                        </div>
-                    </div>
-                    <div class="layui-form-item" th:if="${app}">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="appId"  placeholder="请输入应用 ID" disabled="disabled" th:value="${app?.appId}">
-                        </div>
-                    </div>
-                </td>
-                <th>应用名</th>
-                <td >
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="appName"  placeholder="请输入应用名" required th:value="${app?.appName}">
-                        </div>
-                    </div>
-                </td>
-                <th>是否启用</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <select name="enable">
-                                <option value="1" th:selected="${app?.enable == 1}">是</option>
-                                <option value="0" th:selected="${app?.enable == 0}">否</option>
-                            </select>
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            <tr>
-                <th>所属环境</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <select name="env">
-                                <option th:each="item : ${environments}" th:value="${item.key}" th:selected="${app?.env == item.key}">[[${item.value}]]</option>
-                            </select>
-                        </div>
-                    </div>
-                </td>
-                <th>应用类型</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <select name="appType">
-                                <option th:each="item : ${appTypes}" th:value="${item.key}" th:selected="${app?.appType == item.key}">[[${item.value}]]</option>
-                            </select>
-                            <!--<input class="layui-input" type="text" list="appTypeList" name="appType"  placeholder="请选择应用类型" required th:value="${app?.appType}">
-                            <datalist id="appTypeList">
-                                <option th:each="item : ${appTypes}">[[${item}]]</option>
-                            </datalist>-->
-                        </div>
-                    </div>
-                </td>
-                <th>应用描述</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="description"  placeholder="请输入应用描述" required th:value="${app?.description}">
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            <tr>
-                <th>应用仓库</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="appRepo"  placeholder="请输入应用仓库" required th:value="${app?.appRepo}">
-                        </div>
-                    </div>
-                </td>
-                <th>仓库分支</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="branch"  placeholder="请输入仓库分支" required th:value="${app?.branch}">
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            </tbody>
-        </table>
-        <div class="timo-detail-title">通知配置(数组)</div>
-        <table class="layui-table timo-detail-table">
-            <tbody>
-            <tr th:each="item1:${app?.notifyReceivers}">
-                <th>通知类型</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <select name="notifyType">
-                                <option th:each="item : ${notifyTypes}" th:value="${item.key}">[[${item.value}]]</option>
-                            </select>
-                        </div>
-                    </div>
-                </td>
-                <th>通知接收地址</th>
-                <td >
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="receiver" placeholder="请输入根据通知类型输入通知地址,多个地址使用英文逗号分隔" required th:value="${item1?.receiver}">
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            </tbody>
-        </table>
-        <div class="timo-detail-title">构建配置</div>
-        <table class="layui-table timo-detail-table">
-            <tbody>
-            <tr>
-                <th>代码目录</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="dirname"  placeholder="请输入应用代码目录" required th:value="${app?.dirname}">
-                        </div>
-                    </div>
-                </td>
-                <th>编译目录</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="compileHome"  placeholder="请输入应用编译主目录" required th:value="${app?.compileHome}">
-                        </div>
-                    </div>
-                </td>
-                <th>可执行文件名</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="execBinName"  placeholder="请输入构建生成的可执行文件名" required th:value="${app?.execBinName}">
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            <tr>
-                <th>Dockerfile</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <textarea class="layui-textarea" name="dockerfile" placeholder="请输入 Dockerfile" required th:text="${app?.dockerfile}"></textarea>
-                            <!--<input class="layui-input" type="text" name="dockerfile"  placeholder="请输入 Dockerfile" required th:value="${app?.dockerfile}">-->
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            <tr>
-                <th>仓库认证</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <select name="repoAuthConfig">
-                                <option th:each="item : ${repoAuths}" th:value="${item.key}" th:selected="${app?.repoAuthConfig?.name == item.key}">[[${item.value}]]</option>
-                            </select>
-                        </div>
-                    </div>
-                </td>
-                <th>编译器</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <select name="compilerConfig">
-                                <option th:each="item : ${compilers}" th:value="${item.key}" th:selected="${app?.compilerConfig?.name == item.key}">[[${item.value}]]</option>
-                            </select>
-                        </div>
-                    </div>
-                </td>
-                <th>打包工具</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <select name="packerConfig">
-                                <option th:each="item : ${packers}" th:value="${item.key}" th:selected="${app?.packerConfig?.name == item.key}">[[${item.value}]]</option>
-                            </select>
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            </tbody>
-        </table>
-        <div class="timo-detail-title">部署配置(数组)</div>
-        <table class="layui-table timo-detail-table">
-            <tbody>
-            <tr th:each="item1:${app?.deployConfigs}">
-                <th>机器地址</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <select name="machineIpv4">
-                                <option th:each="item : ${machines}" th:value="${item.key}">[[${item.value}]]</option>
-                            </select>
-                        </div>
-                    </div>
-                </td>
-                <th>启动脚本</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <textarea class="layui-textarea" name="startScript" placeholder="请输入启动脚本" required th:text="${item1?.startScript}"></textarea>
-                        </div>
-                    </div>
-                </td>
-                <th>启动目录</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="startHome"  placeholder="请输入启动目录" required th:value="${item1?.startHome}">
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            </tbody>
-        </table>
-        <div class="timo-detail-title">运行配置</div>
-        <!--<input type="hidden" name="id" th:if="${app}" th:value="${app}"/>-->
-        <table class="layui-table timo-detail-table">
-            <tbody>
-            <tr>
-                <th>HTTP 端口</th>
-                <td>
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="runningConfig.httpPort" placeholder="请输入应用的 HTTP 端口" th:if="${app?.runningConfig?.httpPort}">
-                        </div>
-                    </div>
-                </td>
-                <th>健康检查地址</th>
-                <td >
-                    <div class="layui-form-item">
-                        <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="runningConfig.healthCheck" placeholder="请输入健康检查 URI" required th:value="${app?.runningConfig?.healthCheck}">
-                        </div>
-                    </div>
-                </td>
-            </tr>
-            </tbody>
-        </table>
-        <div class="layui-form-item timo-finally">
-            <button class="layui-btn ajax-submit"><i class="fa fa-check-circle"></i> 保存</button>
-            <button class="layui-btn btn-secondary close-popup"><i class="fa fa-times-circle"></i> 关闭</button>
-        </div>
-    </form>
-</div>
-<script th:replace="/common/template :: script"></script>
-<script type="text/javascript" th:src="@{/js/plugins/jquery-2.2.4.min.js}"></script>
-<script type="text/javascript">
-</script>
-</body>
-</html>

+ 1 - 1
dmaster/src/main/resources/templates/app/config/app/add.html

@@ -19,7 +19,7 @@
                     </div>
                     <div class="layui-form-item" th:if="${app}">
                         <div class="layui-input-inline">
-                            <input class="layui-input" type="text" name="appId" placeholder="请输入应用 ID" disabled="disabled" th:value="${app?.appId}">
+                            <input class="layui-input" type="text" name="appId" disabled="disabled" th:value="${app?.appId}">
                         </div>
                     </div>
                 </td>

+ 50 - 0
dmaster/src/main/resources/templates/app/config/builddir/add.html

@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body>
+<div class="layui-form timo-compile">
+    <form th:action="@{/api/app/config/build/dir}">
+        <input type="hidden" name="id" th:value="${buildDir?.id}"/>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">机器地址</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="machineIpv4" placeholder="请输入机器地址" required th:value="${buildDir?.machineIpv4}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">目录路径</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="dirPath" placeholder="请输入目录路径" required th:value="${buildDir?.dirPath}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">总容量</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="capacity" disabled="disabled" required th:value="${buildDir?.capacity}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">已使用</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="used" disabled="disabled" required th:value="${buildDir?.used}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label">可用</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="available" disabled="disabled" required th:value="${buildDir?.available}">
+            </div>
+        </div>
+        <div class="layui-form-item timo-finally">
+            <button class="layui-btn ajax-submit"><i class="fa fa-check-circle"></i> 保存</button>
+            <button class="layui-btn btn-secondary close-popup"><i class="fa fa-times-circle"></i> 关闭</button>
+        </div>
+    </form>
+</div>
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 63 - 0
dmaster/src/main/resources/templates/app/config/builddir/index.html

@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body class="timo-layout-page">
+<div class="layui-card">
+    <div class="layui-card-header timo-card-header">
+        <span><i class="fa fa-bars"></i> 构建目录</span>
+        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-row timo-card-screen put-row">
+            <div class="pull-right screen-btn-group">
+                <div class="btn-group-right">
+                    <button class="layui-btn open-popup" data-title="添加构建目录" th:attr="data-url=@{/app/config/build/dir/add}"
+                            data-size="800,600">
+                        <i class="fa fa-plus"></i> 添加
+                    </button>
+                </div>
+            </div>
+        </div>
+        <div class="timo-table-wrap">
+            <table class="layui-table timo-table">
+                <thead>
+                <tr>
+                    <th class="timo-table-checkbox">
+                        <label class="timo-checkbox"><input type="checkbox">
+                            <i class="layui-icon layui-icon-ok"></i></label>
+                    </th>
+                    <th class="sortable" data-field="machineIpv4">机器地址</th>
+                    <th class="sortable" data-field="dirPath">目录路径</th>
+                    <th class="sortable" data-field="capacity">总容量</th>
+                    <th class="sortable" data-field="used">已使用</th>
+                    <th class="sortable" data-field="available">可用</th>
+                    <th>操作</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr th:each="item:${list}">
+                    <td><label class="timo-checkbox"><input type="checkbox" th:value="${item.id}">
+                        <i class="layui-icon layui-icon-ok"></i></label></td>
+                    <td th:text="${item.machineIpv4}">机器地址</td>
+                    <td th:text="${item.dirPath}">目录路径</td>
+                    <td th:text="${item.capacity}">总容量</td>
+                    <td th:text="${item.used}">已使用</td>
+                    <td th:text="${item.available}">可用</td>
+                    <td>
+                        <a class="open-popup" data-title="迁移目录" th:attr="data-url=@{'/app/config/build/dir/edit/'+${item.id}}"
+                           data-size="800,600" href="#">迁移目录</a>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+        <div th:replace="/common/fragment :: page"></div>
+    </div>
+</div>
+
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 52 - 0
dmaster/src/main/resources/templates/app/config/compiler/add.html

@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body>
+<div class="layui-form timo-compile">
+    <form th:action="@{/api/app/config/build/compiler}">
+        <input type="hidden" name="id" th:value="${compiler?.id}"/>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">编译类型</label>
+            <div class="layui-input-inline">
+                <select name="type">
+                    <option th:each="item : ${compileTypes}" th:value="${item.key}" th:selected="${compiler?.type == item.key}">[[${item.value}]]</option>
+                </select>
+            </div>
+        </div>
+        <div class="layui-form-item" th:if="${compiler} == null">
+            <label class="layui-form-label required">编译名字</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="name" placeholder="请输入编译名字" required th:value="${compiler?.name}">
+            </div>
+        </div>
+        <div class="layui-form-item" th:if="${compiler} != null">
+            <label class="layui-form-label required">编译名字</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="name" disabled="disabled" required th:value="${compiler?.name}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">编译器主目录</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="homePath" placeholder="请输入编译器主目录" required th:value="${compiler?.homePath}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">编译命令</label>
+            <div class="layui-input-inline">
+                <textarea class="layui-textarea" name="compileCmd" placeholder="请输入编译命令" required th:text="${compiler?.compileCmd}"></textarea>
+            </div>
+        </div>
+        <div class="layui-form-item timo-finally">
+            <button class="layui-btn ajax-submit"><i class="fa fa-check-circle"></i> 保存</button>
+            <button class="layui-btn btn-secondary close-popup"><i class="fa fa-times-circle"></i> 关闭</button>
+        </div>
+    </form>
+</div>
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 31 - 0
dmaster/src/main/resources/templates/app/config/compiler/detail.html

@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+<body>
+    <div class="timo-detail-page">
+        <table class="layui-table timo-detail-table">
+            <tbody>
+            <tr>
+                <th>机器地址</th>
+                <td th:text="${compiler.machineIpv4}"></td>
+                <th>编译类型</th>
+                <td th:text="${compiler.type}"></td>
+                <th>编译名字</th>
+                <td th:text="${compiler.name}"></td>
+            </tr>
+            <tr>
+                <th>编译器主目录</th>
+                <td th:text="${compiler.homePath}"></td>
+            </tr>
+            <tr>
+                <th>编译命令</th>
+                <td>
+                    <textarea class="layui-textarea" readonly="readonly" th:text="${compiler.compileCmd}"></textarea>
+                </td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+<script th:replace="/common/template :: script"></script>
+</body>
+</html>

+ 65 - 0
dmaster/src/main/resources/templates/app/config/compiler/index.html

@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body class="timo-layout-page">
+<div class="layui-card">
+    <div class="layui-card-header timo-card-header">
+        <span><i class="fa fa-bars"></i> 编译配置</span>
+        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-row timo-card-screen put-row">
+            <div class="pull-right screen-btn-group">
+                <div class="btn-group-right">
+                    <button class="layui-btn open-popup" data-title="添加编译配置" th:attr="data-url=@{/app/config/build/compiler/add}"
+                            data-size="640,480">
+                        <i class="fa fa-plus"></i> 添加
+                    </button>
+                </div>
+            </div>
+        </div>
+        <div class="timo-table-wrap">
+            <table class="layui-table timo-table">
+                <thead>
+                <tr>
+                    <th class="timo-table-checkbox">
+                        <label class="timo-checkbox"><input type="checkbox">
+                            <i class="layui-icon layui-icon-ok"></i></label>
+                    </th>
+                    <th class="sortable" data-field="machineIpv4">机器地址</th>
+                    <th class="sortable" data-field="type">编译类型</th>
+                    <th class="sortable" data-field="name">编译名字</th>
+                    <th class="sortable" data-field="compileCmd">编译命令</th>
+                    <th>操作</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr th:each="item:${list}">
+                    <td><label class="timo-checkbox"><input type="checkbox" th:value="${item.id}">
+                        <i class="layui-icon layui-icon-ok"></i></label></td>
+                    <td th:text="${item.machineIpv4}">机器地址</td>
+                    <td th:text="${item.type}">编译类型</td>
+                    <td th:text="${item.name}">编译名字</td>
+                    <td th:text="${item.compileCmd}">编译命令</td>
+                    <td>
+                        <a class="open-popup" data-title="详细" th:attr="data-url=@{'/app/config/build/compiler/detail/'+${item.id}}"
+                           data-size="640,480" href="#">详细</a>
+                        <a class="open-popup" data-title="编辑" th:attr="data-url=@{'/app/config/build/compiler/edit/'+${item.id}}"
+                           data-size="640,480" href="#">编辑</a>
+                        <a class="open-popup" data-title="删除" th:attr="data-url=@{'/app/config/build/compiler/'+${item.id}}"
+                           data-size="800,600" href="#">删除</a>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+        <div th:replace="/common/fragment :: page"></div>
+    </div>
+</div>
+
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 46 - 0
dmaster/src/main/resources/templates/app/config/packer/add.html

@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body>
+<div class="layui-form timo-compile">
+    <form th:action="@{/api/app/config/build/packer}">
+        <input type="hidden" name="id" th:value="${packer?.id}"/>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">打包类型</label>
+            <div class="layui-input-inline">
+                <select name="type">
+                    <option th:each="item : ${packTypes}" th:value="${item.key}" th:selected="${packer?.type == item.key}">[[${item.value}]]</option>
+                </select>
+            </div>
+        </div>
+        <div class="layui-form-item" th:if="${packer} == null">
+            <label class="layui-form-label required">打包名字</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="name" placeholder="请输入打包名字" required th:value="${packer?.name}">
+            </div>
+        </div>
+        <div class="layui-form-item" th:if="${packer} != null">
+            <label class="layui-form-label required">打包名字</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="name" disabled="disabled" required th:value="${packer?.name}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">存放位置</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="targetPath" placeholder="请输入存放位置" required th:value="${packer?.targetPath}">
+            </div>
+        </div>
+        <div class="layui-form-item timo-finally">
+            <button class="layui-btn ajax-submit"><i class="fa fa-check-circle"></i> 保存</button>
+            <button class="layui-btn btn-secondary close-popup"><i class="fa fa-times-circle"></i> 关闭</button>
+        </div>
+    </form>
+</div>
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 25 - 0
dmaster/src/main/resources/templates/app/config/packer/detail.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+<body>
+    <div class="timo-detail-page">
+        <table class="layui-table timo-detail-table">
+            <tbody>
+            <tr>
+                <th>机器地址</th>
+                <td th:text="${packer.machineIpv4}"></td>
+                <th>打包类型</th>
+                <td th:text="${packer.type}"></td>
+            </tr>
+            <tr>
+                <th>打包名字</th>
+                <td th:text="${packer.name}"></td>
+                <th>存放位置</th>
+                <td th:text="${packer.targetPath}"></td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+<script th:replace="/common/template :: script"></script>
+</body>
+</html>

+ 65 - 0
dmaster/src/main/resources/templates/app/config/packer/index.html

@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body class="timo-layout-page">
+<div class="layui-card">
+    <div class="layui-card-header timo-card-header">
+        <span><i class="fa fa-bars"></i> 打包配置</span>
+        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-row timo-card-screen put-row">
+            <div class="pull-right screen-btn-group">
+                <div class="btn-group-right">
+                    <button class="layui-btn open-popup" data-title="添加打包配置" th:attr="data-url=@{/app/config/build/packer/add}"
+                            data-size="640,480">
+                        <i class="fa fa-plus"></i> 添加
+                    </button>
+                </div>
+            </div>
+        </div>
+        <div class="timo-table-wrap">
+            <table class="layui-table timo-table">
+                <thead>
+                <tr>
+                    <th class="timo-table-checkbox">
+                        <label class="timo-checkbox"><input type="checkbox">
+                            <i class="layui-icon layui-icon-ok"></i></label>
+                    </th>
+                    <th class="sortable" data-field="machineIpv4">机器地址</th>
+                    <th class="sortable" data-field="type">打包类型</th>
+                    <th class="sortable" data-field="name">打包名字</th>
+                    <th class="sortable" data-field="targetPath">存放位置</th>
+                    <th>操作</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr th:each="item:${list}">
+                    <td><label class="timo-checkbox"><input type="checkbox" th:value="${item.id}">
+                        <i class="layui-icon layui-icon-ok"></i></label></td>
+                    <td th:text="${item.machineIpv4}">机器地址</td>
+                    <td th:text="${item.type}">打包类型</td>
+                    <td th:text="${item.name}">打包名字</td>
+                    <td th:text="${item.targetPath}">存放位置</td>
+                    <td>
+                        <a class="open-popup" data-title="详细" th:attr="data-url=@{'/app/config/build/packer/detail/'+${item.id}}"
+                           data-size="640,480" href="#">详细</a>
+                        <a class="open-popup" data-title="编辑" th:attr="data-url=@{'/app/config/build/packer/edit/'+${item.id}}"
+                           data-size="640,480" href="#">编辑</a>
+                        <a class="open-popup" data-title="删除" th:attr="data-url=@{'/app/config/build/packer/'+${item.id}}"
+                           data-size="800,600" href="#">删除</a>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+        <div th:replace="/common/fragment :: page"></div>
+    </div>
+</div>
+
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 0 - 87
dmaster/src/main/resources/templates/app/config/proj/index.html

@@ -1,87 +0,0 @@
-<!DOCTYPE html>
-<html xmlns:th="http://www.thymeleaf.org"
-      xmlns:mo="https://gitee.com/aun/Timo">
-<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
-<body class="timo-layout-page">
-<div class="layui-card">
-    <div class="layui-card-header timo-card-header">
-        <span><i class="fa fa-bars"></i> 项目配置</span>
-        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
-    </div>
-    <div class="layui-card-body">
-        <div class="layui-row timo-card-screen put-row">
-            <div class="pull-left layui-form-pane timo-search-box">
-                <div class="layui-inline">
-                    <label class="layui-form-label">环境</label>
-                    <div class="layui-input-block timo-search-status">
-                        <select class="timo-search-select" name="status" mo:dict="SEARCH_STATUS"
-                                mo-selected="${param.env}"></select>
-                    </div>
-                </div>
-                <div class="layui-inline">
-                    <label class="layui-form-label">应用</label>
-                    <div class="layui-input-block">
-                        <input type="text" name="appId" th:value="${param.appId}" placeholder="请输入应用"
-                               autocomplete="off" class="layui-input">
-                    </div>
-                </div>
-                <div class="layui-inline">
-                    <button class="layui-btn timo-search-btn">
-                        <i class="fa fa-search"></i>
-                    </button>
-                </div>
-            </div>
-        </div>
-        <div class="timo-table-wrap">
-            <table class="layui-table timo-table">
-                <thead>
-                <tr>
-                    <th class="timo-table-checkbox">
-                        <label class="timo-checkbox"><input type="checkbox">
-                            <i class="layui-icon layui-icon-ok"></i></label>
-                    </th>
-                    <th class="sortable" data-field="appId">应用</th>
-                    <th class="sortable" data-field="branch">分支</th>
-                    <th class="sortable" data-field="commitId">版本</th>
-                    <th class="sortable" data-field="commitTime">提交时间</th>
-                    <th class="sortable" data-field="result">构建结果</th>
-                    <th class="sortable" data-field="buildTime">构建时间</th>
-                    <th class="sortable" data-field="buildBy">构建用户</th>
-                    <th>操作</th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr th:each="item:${list}">
-                    <td><label class="timo-checkbox"><input type="checkbox" th:value="${item.appId}">
-                        <i class="layui-icon layui-icon-ok"></i></label></td>
-                    <td>
-                        <a class="open-popup" data-title="应用配置详情" data-size="1000,600" href="#"
-                           th:text="${item.appId}" th:attr="data-url=@{'/app/config/app/detail/'+${item.appId}}"></a>
-                    </td>
-                    <td th:text="${item.branch}">分支</td>
-                    <td th:text="${item.appId}">版本</td>
-                    <td th:text="${item.appId}">提交时间</td>
-                    <td>
-                        <a class="open-popup" data-title="构建结果" data-size="800,600" href="#"
-                           th:text="${item.appId}" th:attr="data-url=@{'/app/log/build/'+${item.appId} + '/result'}"></a>
-                    </td>
-                    <td th:text="${item.appId}">构建时间</td>
-                    <td th:text="${item.appId}">构建用户</td>
-                    <td>
-                        <a class="ajax-post" th:href="@{'/api/app/bd/update?appId='+${item.appId}}">更新</a>
-                        <a class="ajax-post" th:href="@{'/api/app/bd/build?appId='+${item.appId}}">构建</a>
-                        <a class="open-popup" data-title="应用部署" th:attr="data-url=@{'/app/deploy/' + ${item.appId}}"
-                           data-size="1000,600" href="#">部署</a>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-        </div>
-        <div th:replace="/common/fragment :: page"></div>
-    </div>
-</div>
-<script th:replace="/common/template :: script"></script>
-<script type="text/javascript">
-</script>
-</body>
-</html>

+ 66 - 0
dmaster/src/main/resources/templates/app/config/repoauth/add.html

@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body>
+<div class="layui-form timo-compile">
+    <form th:action="@{/api/app/config/build/repoauth}">
+        <input type="hidden" name="id" th:value="${repoAuth?.id}"/>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">仓库类型</label>
+            <div class="layui-input-inline">
+                <select name="type">
+                    <option th:each="item : ${repos}" th:value="${item.key}" th:selected="${repoAuth?.type == item.key}">[[${item.value}]]</option>
+                </select>
+            </div>
+        </div>
+        <div class="layui-form-item" th:if="${repoAuth} == null">
+            <label class="layui-form-label required">认证名字</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="name" placeholder="请输入认证名字" required th:value="${repoAuth?.name}">
+            </div>
+        </div>
+        <div class="layui-form-item" th:if="${repoAuth} != null">
+            <label class="layui-form-label required">认证名字</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="name" disabled="disabled" required th:value="${repoAuth?.name}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">认证类型</label>
+            <div class="layui-input-inline">
+                <select name="authType">
+                    <option th:each="item : ${auths}" th:value="${item.key}" th:selected="${repoAuth?.authType == item.key}">[[${item.value}]]</option>
+                </select>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">RSA 私钥(ssh)</label>
+            <div class="layui-input-inline">
+                <textarea class="layui-textarea" name="rsaPrikey" placeholder="请输入 RSA 私钥" required th:text="${repoAuth?.rsaPrikey}"></textarea>
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">用户名(http)</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="username" placeholder="请输入用户名" required th:value="${repoAuth?.username}">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <label class="layui-form-label required">密码(http)</label>
+            <div class="layui-input-inline">
+                <input class="layui-input" type="text" name="password" placeholder="请输入密码" required th:value="${repoAuth?.password}">
+            </div>
+        </div>
+        <div class="layui-form-item timo-finally">
+            <button class="layui-btn ajax-submit"><i class="fa fa-check-circle"></i> 保存</button>
+            <button class="layui-btn btn-secondary close-popup"><i class="fa fa-times-circle"></i> 关闭</button>
+        </div>
+    </form>
+</div>
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 35 - 0
dmaster/src/main/resources/templates/app/config/repoauth/detail.html

@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+<body>
+    <div class="timo-detail-page">
+        <table class="layui-table timo-detail-table">
+            <tbody>
+            <tr>
+                <th>仓库类型</th>
+                <td th:text="${repoAuth.type}"></td>
+                <th>认证名字</th>
+                <td th:text="${repoAuth.name}"></td>
+            </tr>
+            <tr>
+                <th>认证方式</th>
+                <td th:text="${repoAuth.authType}"></td>
+                <span th:if="${repoAuth.authType} == 'ssh'">
+                    <th>RSA 私钥</th>
+                    <td>
+                        <textarea class="layui-textarea" readonly="readonly" th:text="${repoAuth.rsaPrikey}"></textarea>
+                    </td>
+                </span>
+                <span th:if="${repoAuth.authType} == 'http'">
+                    <th>用户名</th>
+                    <td th:text="${repoAuth.username}"></td>
+                    <th>密码</th>
+                    <td th:text="${repoAuth.password}"></td>
+                </span>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+<script th:replace="/common/template :: script"></script>
+</body>
+</html>

+ 63 - 0
dmaster/src/main/resources/templates/app/config/repoauth/index.html

@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
+
+<body class="timo-layout-page">
+<div class="layui-card">
+    <div class="layui-card-header timo-card-header">
+        <span><i class="fa fa-bars"></i> 仓库认证</span>
+        <i class="layui-icon layui-icon-refresh refresh-btn"></i>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-row timo-card-screen put-row">
+            <div class="pull-right screen-btn-group">
+                <div class="btn-group-right">
+                    <button class="layui-btn open-popup" data-title="添加仓库认证" th:attr="data-url=@{/app/config/build/repoauth/add}"
+                            data-size="640,480">
+                        <i class="fa fa-plus"></i> 添加
+                    </button>
+                </div>
+            </div>
+        </div>
+        <div class="timo-table-wrap">
+            <table class="layui-table timo-table">
+                <thead>
+                <tr>
+                    <th class="timo-table-checkbox">
+                        <label class="timo-checkbox"><input type="checkbox">
+                            <i class="layui-icon layui-icon-ok"></i></label>
+                    </th>
+                    <th class="sortable" data-field="type">仓库类型</th>
+                    <th class="sortable" data-field="name">认证名字</th>
+                    <th class="sortable" data-field="authType">认证类型</th>
+                    <th>操作</th>
+                </tr>
+                </thead>
+                <tbody>
+                <tr th:each="item:${list}">
+                    <td><label class="timo-checkbox"><input type="checkbox" th:value="${item.id}">
+                        <i class="layui-icon layui-icon-ok"></i></label></td>
+                    <td th:text="${item.type}">仓库类型</td>
+                    <td th:text="${item.name}">认证名字</td>
+                    <td th:text="${item.authType}">认证类型</td>
+                    <td>
+                        <a class="open-popup" data-title="详细" th:attr="data-url=@{'/app/config/build/repoauth/detail/'+${item.id}}"
+                           data-size="640,480" href="#">详细</a>
+                        <a class="open-popup" data-title="编辑" th:attr="data-url=@{'/app/config/build/repoauth/edit/'+${item.id}}"
+                           data-size="640,480" href="#">编辑</a>
+                        <a class="open-popup" data-title="删除" th:attr="data-url=@{'/app/config/build/repoauth/'+${item.id}}"
+                           data-size="800,600" href="#">删除</a>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+        <div th:replace="/common/fragment :: page"></div>
+    </div>
+</div>
+
+<script th:replace="/common/template :: script"></script>
+<script type="text/javascript">
+</script>
+</body>
+</html>

+ 1 - 196
dmaster/src/main/resources/templates/home/index.html

@@ -108,201 +108,6 @@
         </div>
     </div>
 </div>
-<div class="layui-row layui-col-space15">
-    <div class="layui-col-md8">
-        <div class="layui-card">
-            <div class="layui-card-header">项目介绍</div>
-            <div class="layui-card-body project-introduce">
-                <blockquote class="layui-elem-quote layui-quote-nm">
-                    TIMO后台管理系统,基于SpringBoot2.0 + Spring Data Jpa + Thymeleaf + Shiro 开发的后台管理系统,采用分模块的方式便于开发和维护,目前支持的功能有:权限管理、部门管理、字典管理、日志记录、文件上传、代码生成等,为快速开发后台系统而生的脚手架!
-                    <div>开源协议:Apache License 2.0</div>
-                    <div>开源地址:<a href="https://gitee.com/aun/Timo">https://gitee.com/aun/Timo</a></div>
-                </blockquote>
-                <div>
-                    <h4>技术选型</h4>
-                    <ol>
-                        <li>后端技术:SpringBoot + Spring Data Jpa + Thymeleaf + Shiro + EhCache</li>
-                        <li>前端技术:Layui + Jquery + zTree + Font-awesome</li>
-                    </ol>
-                </div>
-                <div>
-                    <h4>功能列表</h4>
-                    <ol>
-                        <li>用户管理:用于管理后台系统的用户,可进行增删改查等操作。</li>
-                        <li>角色管理:分配权限的最小单元,通过角色给用户分配权限。</li>
-                        <li>菜单管理:用于配置系统菜单,同时也作为权限资源。</li>
-                        <li>部门管理:通过不同的部门来管理和区分用户。</li>
-                        <li>字典管理:对一些需要转换的数据进行统一管理,如:男、女等。</li>
-                        <li>行为日志:用于记录用户对系统的操作,同时监视系统运行时发生的错误。</li>
-                        <li>文件上传:内置了文件上传接口,方便开发者使用文件上传功能。</li>
-                        <li>代码生成:可以帮助开发者快速开发项目,减少不必要的重复操作,花更多精力注重业务实现。</li>
-                        <li>表单构建:通过拖拽的方式快速构建一个表单模块。</li>
-                        <li>数据接口:根据业务代码自动生成相关的api接口文档</li>
-                    </ol>
-                </div>
-            </div>
-        </div>
-        <div class="layui-row layui-col-space15">
-            <div class="layui-col-md6">
-                <div class="layui-card">
-                    <div class="layui-card-header">项目信息</div>
-                    <div class="layui-card-body">
-                        <ul>
-                            <li><i class="fa fa-paper-plane"></i> 版本:<a href="https://gitee.com/aun/Timo">v2.0.3</a></li>
-                            <li><i class="fa fa-coffee"></i> 作者:<a href="https://gitee.com/aun">小懒虫</a></li>
-                            <li><i class="fa fa-flag"></i> 官网:<a href="http://www.linln.cn">http://www.linln.cn</a></li>
-                            <li><i class="fa fa-qq"></i> QQ群:<a href="https://jq.qq.com/?_wv=1027&k=5RCnDCO">941209502(已满)</a> <a href="https://jq.qq.com/?_wv=1027&k=5AIEf1E">545633945</a></li>
-                            <li><i class="fa fa-book"></i> 开发文档:<a href="http://www.linln.cn/docs">TIMO开发文档.在线</a></li>
-                        </ul>
-                    </div>
-                </div>
-            </div>
-            <div class="layui-col-md6">
-                <div class="layui-card">
-                    <div class="layui-card-header">捐赠</div>
-                    <div class="layui-card-body">
-                        <div class="alert alert-info">开源不易,您的支持就是我的动力!</div>
-                        <img style="width: 100%" th:src="@{/imgs/alipay.png}"/>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <div class="layui-col-md4">
-        <div class="layui-card">
-            <div class="layui-card-header">更新日志</div>
-            <div class="layui-card-body">
-                <ul class="layui-timeline">
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v2.0.3</h3>
-                            <p>
-                                1. 更新:重命名菜单类型为:目录、菜单、按钮<br>
-                                2. 更新:重写Shiro“记住我”系列化数据,减少cookie体积<br>
-                                3. 新增:获取用户角色列表方法<br>
-                                4. 修复:获取部门数据时延迟加载超时问题<br>
-                                5. 修复:将jq版本改为2.2.4,解决layui弹出窗口最大化问题<br>
-                                6. 新增:项目配置项,可直接通过yml文件配置Shiro和XSS防护忽略规则<br>
-                                7. 新增:ResultExceptionError和ResultExceptionSuccess异常类<br>
-                                8. 修复:若干页面显示问题,优化加载时提示<br>
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v2.0.2</h3>
-                            <p>
-                                1.优化:根据【阿里巴巴Java开发手册】对代码进行优化处理!<br>
-                                2.新增:上传文件路径输出为全路径方法<br>
-                                3.更新:介绍文档及HTML页面头部信息<br>
-                                4.更新:去掉“更多按钮”,直接显示隐藏内容,不再需要点击按钮滑动内容<br>
-                                5.修复:编译时警告信息!<br>
-                                6.修复:代码生成新模块版本号问题<br>
-                                7.修复:接口无法继承多个父接口的问题<br>
-                                8.修复:jwt组件中添加获取用户名的方法<br>
-                                9.修复:代码生成时控制器保存地址问题<br>
-                                10.修复:部门、菜单控制器更新数据时,pids无法更新<br>
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v2.0.1</h3>
-                            <p>
-                                1.新增:加入JWT TOKEN鉴权机制,实现多端的权限验证!<br>
-                                2.更新:模块化全局统一异常处理机制及项目配置,降低模块间的耦合性!<br>
-                                3.修复:部分环境下代码生成模板文件编译时的后缀遗留问题!<br>
-                                4.修复:部门更新导致pids字段为空的问题!<br>
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v2.0</h3>
-                            <p>
-                                1.重构项目结构,引入组件及业务组概念<br>
-                                2.前后台分离部署,可以针对前台进行性能优化<br>
-                                3.优化逻辑删除功能,限制查询已删除的数据<br>
-                                4.重构代码生成功能解析方式<br>
-                                5.优化弹出式窗口,加入最大化及自动适应大小<br>
-                                6.优化数据列表在小窗口下显示混乱问题
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v1.0.8</h3>
-                            <p>
-                                1.重构字典模块,简化字典操作<br>
-                                2.修复个人信息修改时不通过问题<br>
-                                3.修复用户名修改报错问题,防止脏数据报错<br>
-                                4.修复上传文件无法访问的bug<br>
-                                5.修复生成实体类Text类型的bug
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v1.0.6</h3>
-                            <p>
-                                加入导入导出功能
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v1.0.5</h3>
-                            <p>
-                                1.加入QuerySpec动态查询实例<br>
-                                2.加入选择排序功能<br>
-                                3.加入xss防护功能<br>
-                                4.加入swagger数据接口文档
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v1.0.1</h3>
-                            <p>
-                                1.加入部门管理<br>
-                                2.更新项目开源协议<br>
-                                3.支持第三级子菜单
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <h3 class="layui-timeline-title">v1.0</h3>
-                            <p>
-                                正式发布v1.0系统<br>
-                                1.权限管理<br>
-                                2.字典管理<br>
-                                3.日志管理<br>
-                                4.代码生成
-                            </p>
-                        </div>
-                    </li>
-                    <li class="layui-timeline-item">
-                        <i class="layui-icon layui-timeline-axis">&#xe63f;</i>
-                        <div class="layui-timeline-content layui-text">
-                            <div class="layui-timeline-title">小懒虫</div>
-                        </div>
-                    </li>
-                </ul>
-            </div>
-        </div>
-    </div>
-</div>
 <script th:replace="/common/template :: script"></script>
 </body>
-</html>
-
+</html>