Kaynağa Gözat

项目配置部分的前端页面基本完成

reghao 4 yıl önce
ebeveyn
işleme
47ea10b1f2

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

@@ -5,7 +5,9 @@ import cn.reghao.autodop.dmaster.app.constant.EnvType;
 import cn.reghao.autodop.dmaster.app.constant.NotifyType;
 import cn.reghao.autodop.dmaster.app.db.app.AppConfigQuery;
 import cn.reghao.autodop.dmaster.app.entity.config.AppOrchestration;
+import cn.reghao.autodop.dmaster.app.entity.config.ProjOrchestration;
 import cn.reghao.autodop.dmaster.app.repository.config.AppOrchestrationRepository;
+import cn.reghao.autodop.dmaster.app.repository.config.ProjOrchestrationRepository;
 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;
@@ -16,13 +18,10 @@ 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.AllArgsConstructor;
-import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
 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.*;
@@ -41,6 +40,7 @@ import java.util.stream.Collectors;
 public class AppConfigPageController {
     private AppConfigQuery appConfigQuery;
     private AppOrchestrationRepository appRepository;
+    private ProjOrchestrationRepository projRepository;
     private RepoAuthConfigRepository repoAuthRepository;
     private CompilerConfigRepository compilerRepository;
     private PackerConfigRepository packerRepository;
@@ -48,12 +48,14 @@ public class AppConfigPageController {
 
     public AppConfigPageController(AppConfigQuery appConfigQuery,
                                    AppOrchestrationRepository appRepository,
+                                   ProjOrchestrationRepository projRepository,
                                    RepoAuthConfigRepository repoAuthRepository,
                                    CompilerConfigRepository compilerRepository,
                                    PackerConfigRepository packerRepository,
                                    MachineInfoRepository machineRepository) {
         this.appConfigQuery = appConfigQuery;
         this.appRepository = appRepository;
+        this.projRepository = projRepository;
         this.repoAuthRepository = repoAuthRepository;
         this.compilerRepository = compilerRepository;
         this.packerRepository = packerRepository;
@@ -94,11 +96,11 @@ public class AppConfigPageController {
 
     @GetMapping("/app/add")
     public String addAppConfigPage(Model model) {
-        setModel(model);
+        setAppModel(model);
         return "/app/config/app/add";
     }
 
-    private void setModel(Model model) {
+    private void setAppModel(Model model) {
         List<KeyValue> envs = new ArrayList<>();
         for (EnvType envType : EnvType.values()) {
             envs.add(new KeyValue(envType.name(), envType.name()));
@@ -146,7 +148,7 @@ public class AppConfigPageController {
 
     @GetMapping("/app/edit/{id}")
     public String editAppConfigPage(@PathVariable("id") AppOrchestration app, Model model) {
-        setModel(model);
+        setAppModel(model);
         model.addAttribute("app", app);
         return "/app/config/app/add";
     }
@@ -167,18 +169,69 @@ public class AppConfigPageController {
 
     @ApiOperation(value = "项目配置页面")
     @GetMapping("/proj")
-    public String projConfigPage(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"));
+    public String projConfigPage(@RequestParam(value = "projName", required = false) String projName, Model model) {
 
-        Page<AppOrchestration> appPage = appRepository.findByEnableTrueAndEnv(env, pageRequest);
-        PageList<AppOrchestration> pageList = PageList.pageList(appPage);
+        /*if (projName != null) {
+            Map<String, String> map = new HashMap<>();
+            map.put("projName", projName);
+            List<AppOrchestration> list = appConfigQuery.query(map);
+            Page<AppOrchestration> page = new PageImpl<>(list);
+            PageList<AppOrchestration> pageList = PageList.pageList(page);
 
-        model.addAttribute("page", appPage);
+            model.addAttribute("page", page);
+            model.addAttribute("list", pageList.getList());
+            return "/app/config/app/index";
+        }*/
+
+        PageRequest pageRequest = PageSort.pageRequest();
+        Page<ProjOrchestration> page = projRepository.findByIsDeleteFalse(pageRequest);
+        PageList<ProjOrchestration> pageList = PageList.pageList(page);
+
+        model.addAttribute("page", page);
         model.addAttribute("list", pageList.getList());
         return "/app/config/proj/index";
     }
+
+    @GetMapping("/proj/add")
+    public String addProjConfigPage(Model model) {
+        setProjModel(model);
+        return "/app/config/proj/add";
+    }
+
+    private void setProjModel(Model model) {
+        List<KeyValue> repoAuths = repoAuthRepository.findAllByIsDeleteFalse().stream()
+                .map(repoAuthConfig -> new KeyValue(String.valueOf(repoAuthConfig.getId()), repoAuthConfig.getName()))
+                .collect(Collectors.toList());
+        List<KeyValue> compilers = compilerRepository.findAllByIsDeleteFalse().stream()
+                .map(compilerConfig -> new KeyValue(String.valueOf(compilerConfig.getId()), compilerConfig.getName()))
+                .collect(Collectors.toList());
+        List<KeyValue> packers = packerRepository.findAllByIsDeleteFalse().stream()
+                .map(packerConfig -> new KeyValue(String.valueOf(packerConfig.getId()), packerConfig.getName()))
+                .collect(Collectors.toList());
+
+        model.addAttribute("repoAuths", repoAuths);
+        model.addAttribute("compilers", compilers);
+        model.addAttribute("packers", packers);
+    }
+
+    @GetMapping("/proj/edit/{id}")
+    public String editProjConfigPage(@PathVariable("id") ProjOrchestration proj, Model model) {
+        setAppModel(model);
+        model.addAttribute("proj", proj);
+        return "/app/config/proj/add";
+    }
+
+    @GetMapping("/proj/copy/{id}")
+    public String copyProjConfigPage(@PathVariable("id") ProjOrchestration proj, Model model) {
+        model.addAttribute("proj", proj);
+        return "/app/config/proj/copy";
+    }
+
+    @ApiOperation(value = "项目配置详情页面")
+    @GetMapping("/proj/detail/{projId}")
+    public String projConfigDetailPage(@PathVariable("projId") String projId, Model model) {
+        ProjOrchestration proj = projRepository.findByIsDeleteFalseAndProjId(projId);
+        model.addAttribute("proj", proj);
+        return "/app/config/proj/detail";
+    }
 }

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

@@ -136,4 +136,21 @@ public class AppPageController {
         model.addAttribute("list", pageList.getList());
         return "/app/log";
     }
+
+    @ApiOperation(value = "应用备份还原页面")
+    @GetMapping("/bak")
+    public String appBakPage(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"));
+
+        Page<AppBuilding> appBuildings = appBuildingRepository.findAllByEnv(env, pageRequest);
+        PageList<AppBuilding> pageList = PageList.pageList(appBuildings);
+
+        model.addAttribute("page", appBuildings);
+        model.addAttribute("list", pageList.getList());
+        return "/app/bak";
+    }
 }

+ 2 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/config/ProjOrchestration.java

@@ -21,13 +21,12 @@ import javax.persistence.*;
 public class ProjOrchestration extends BaseEntity<Integer> implements Cloneable {
     @Column(nullable = false, unique = true)
     private String projId;
+    private String projName;
     private String description;
 
-    @Column(nullable = false)
     private String projRepo;
-    // 应用代码所在目录的名字
-    @Column(nullable = false)
     private String dirname;
+
     // 同一个项目内所有应用的构建策略是相同的
     @ManyToOne(cascade = CascadeType.PERSIST)
     @JoinColumn(name = "repo_auth_config_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))

+ 3 - 5
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/repository/config/ProjOrchestrationRepository.java

@@ -1,6 +1,8 @@
 package cn.reghao.autodop.dmaster.app.repository.config;
 
 import cn.reghao.autodop.dmaster.app.entity.config.ProjOrchestration;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
 
@@ -13,9 +15,5 @@ import javax.transaction.Transactional;
  */
 public interface ProjOrchestrationRepository extends JpaRepository<ProjOrchestration, Integer> {
     ProjOrchestration findByIsDeleteFalseAndProjId(String projId);
-    //Page<ProjOrchestration> findByIsDeleteFalseAndEnv(String env, Pageable pageable);
-
-    @Modifying
-    @Transactional
-    void deleteByProjId(String projId);
+    Page<ProjOrchestration> findByIsDeleteFalse(Pageable pageable);
 }

+ 96 - 0
dmaster/src/main/resources/templates/app/bak.html

@@ -0,0 +1,96 @@
+<!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" th:attr="data-url=@{'/app/build/list?env=' + ${env}}">
+    <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">
+                <div class="layui-inline">
+                    <label class="layui-form-label">环境</label>
+                    <div class="layui-input-block timo-search-status">
+                        <select id="getPageByEnv" class="timo-search-select" name="env" onchange="getPageByEnv()"
+                                mo:dict="ENVIRONMENT" mo-selected="${env}"></select>
+                    </div>
+                </div>
+                <div class="layui-inline timo-search-box">
+                    <label class="layui-form-label">应用 ID</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="appId" th:value="${param.appName}" placeholder="请输入应用 ID"
+                               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">应用 ID</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="1200,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.commitId}">版本</td>
+                    <td th:text="${item.commitTime}">提交时间</td>
+                    <td>
+                        <a class="open-popup" data-title="构建结果" data-size="640,480" href="#"
+                           th:text="${item.buildResult}" th:attr="data-url=@{'/app/log/build/'+${item.buildLogId} + '/result'}"></a>
+                    </td>
+                    <td th:text="${item.buildTime}">构建时间</td>
+                    <td th:text="${item.buildBy}">构建用户</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.buildLogId}}"
+                           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" th:src="@{/js/plugins/jquery-2.2.4.min.js}"></script>
+<script type="text/javascript">
+    function getPageByEnv() {
+        var selectedOption = $("#getPageByEnv option:selected")
+        var param = selectedOption.text()
+        url = '?env=' + param
+        window.location.href = window.location.pathname + url;
+    }
+</script>
+</body>
+</html>

+ 111 - 0
dmaster/src/main/resources/templates/app/config/proj/add.html

@@ -0,0 +1,111 @@
+<!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/proj}">
+        <input type="hidden" name="id" th:if="${proj}" th:value="${proj?.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="!${proj}">
+                        <div class="layui-input-inline">
+                            <input class="layui-input" type="text" name="projId" placeholder="请输入项目 ID" required th:value="${proj?.projId}">
+                        </div>
+                    </div>
+                    <div class="layui-form-item" th:if="${proj}">
+                        <div class="layui-input-inline">
+                            <input class="layui-input" type="text" name="projId" disabled="disabled" th:value="${proj?.projId}">
+                        </div>
+                    </div>
+                </td>
+                <th>项目名</th>
+                <td >
+                    <div class="layui-form-item">
+                        <div class="layui-input-inline">
+                            <input class="layui-input" type="text" name="projName" placeholder="请输入项目名" required th:value="${proj?.projName}">
+                        </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="${proj?.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="projRepo"  placeholder="请输入项目仓库" required th:value="${proj?.projRepo}">
+                        </div>
+                    </div>
+                </td>
+                <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="${proj?.dirname}">
+                        </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">
+                            <select name="repoAuthConfig">
+                                <option th:each="item : ${repoAuths}" th:value="${item.key}" th:selected="${proj?.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="${proj?.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="${proj?.packerConfig?.name == item.key}">[[${item.value}]]</option>
+                            </select>
+                        </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>

+ 57 - 0
dmaster/src/main/resources/templates/app/config/proj/detail.html

@@ -0,0 +1,57 @@
+<!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">
+        <div class="timo-detail-title">基本信息</div>
+        <table class="layui-table timo-detail-table">
+            <tbody>
+            <tr>
+                <th>项目 ID</th>
+                <td th:text="${proj.projId}"></td>
+                <th>项目名称</th>
+                <td th:text="${proj.projName}"></td>
+                <th>项目描述</th>
+                <td th:text="${proj.description}"></td>
+            </tr>
+            <tr>
+                <th>项目仓库</th>
+                <td th:text="${proj.projRepo}"></td>
+                <th>项目目录</th>
+                <td th:text="${proj.dirname}"></td>
+            </tr>
+            </tbody>
+        </table>
+        <div class="timo-detail-title">构建配置</div>
+        <table class="layui-table timo-detail-table">
+            <tbody>
+            <tr>
+                <th>仓库类型</th>
+                <td th:text="${proj.repoAuthConfig.type}"></td>
+                <th>仓库名字</th>
+                <td th:text="${proj.repoAuthConfig.name}"></td>
+                <th>认证类型</th>
+                <td th:text="${proj.repoAuthConfig.authType}"></td>
+            </tr>
+            <tr>
+                <th>编译器类型</th>
+                <td th:text="${proj.compilerConfig.type}"></td>
+                <th>编译器名字</th>
+                <td th:text="${proj.compilerConfig.name}"></td>
+                <th>编译命令</th>
+                <td th:text="${proj.compilerConfig.compileCmd}"></td>
+            </tr>
+            <tr>
+                <th>打包类型</th>
+                <td th:text="${proj.packerConfig.type}"></td>
+                <th>打包名字</th>
+                <td th:text="${proj.packerConfig.name}"></td>
+                <th>打包路径</th>
+                <td th:text="${proj.packerConfig.targetPath}"></td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+<script th:replace="/common/template :: script"></script>
+</body>
+</html>

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

@@ -0,0 +1,89 @@
+<!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>
+        <a th:href="@{/proj/config/proj/export}"><i class="fa fa-download"></i></a>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-row timo-card-screen put-row">
+            <div class="layui-row timo-card-screen put-row">
+                <div class="pull-left layui-form-pane">
+                    <div class="layui-inline timo-search-box">
+                        <label class="layui-form-label">项目</label>
+                        <div class="layui-input-block">
+                            <input type="text" name="projName" th:value="${param.projName}" 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="pull-right screen-btn-group">
+                <div class="btn-group-right">
+                    <button class="layui-btn open-popup" data-title="添加项目" th:attr="data-url=@{/app/config/proj/add}"
+                            data-size="1200,600">
+                        <i class="fa fa-plus"></i> 添加
+                    </button>
+                    <div class="btn-group">
+                        <button class="layui-btn">批量操作<span class="caret"></span></button>
+                        <dl class="layui-nav-child layui-anim layui-anim-upbit">
+                            <dd><a class="ajax-status" th:href="@{/api/app/config/proj/enable}">启用</a></dd>
+                            <dd><a class="ajax-status" th:href="@{/api/app/config/proj/disable}">禁用</a></dd>
+                        </dl>
+                    </div>
+                </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="projName">项目 ID</th>
+                    <th class="sortable" data-field="projName">项目名</th>
+                    <th class="sortable" data-field="projRepo">项目仓库</th>
+                    <th class="sortable" data-field="dirname">项目目录</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.projId}">项目 ID</td>
+                    <td th:text="${item.projName}">项目名</td>
+                    <td th:text="${item.projRepo}">项目仓库</td>
+                    <td th:text="${item.dirname}">项目目录</td>
+                    <td>
+                        <a class="open-popup" data-title="项目详细信息" th:attr="data-url=@{'/app/config/proj/detail/'+${item.projId}}"
+                           data-size="1200,600" href="#">详细</a>
+                        <a class="open-popup" data-title="编辑" th:attr="data-url=@{'/app/config/proj/edit/'+${item.id}}"
+                           data-size="1200,600" href="#">编辑</a>
+                        <a class="ajax-delete" th:attr="data-msg='确定要删除 '+ ${item.projId} + '?'"
+                           th:href="@{'/api/app/config/proj/' + ${item.id}}">删除</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>